aws-amplify / amplify-cli

The AWS Amplify CLI is a toolchain for simplifying serverless web and mobile development.
Apache License 2.0
2.82k stars 818 forks source link

DataStore: Throws "UpdateItem on versioned data source requires the _version to be provided." when sending a mutation #6315

Closed PeteDuncanson closed 3 years ago

PeteDuncanson commented 3 years ago

Describe the bug

When trying to update an existing model via DataStore GraphQL throws the following error in the console and in the network tab:

"UpdateItem on versioned data source requires the _version to be provided."

Yet the code is good and the _version field is provided. Seems that this was caused by my resolver (added via Amplify not manually) for the update mutation wasn't DataStore aware (ie none of the required fields for DataStore where added to the resolver.

This was discussed last weekend in the Discord channel chat here https://discordapp.com/channels/705853757799399426/735987596462653461/789553458625249280

To Reproduce

Not sure how it got into this state. Sometimes I kill the amplify push (using Ctrl-C but only before it starts actually uploading stuff, if its got that far I leave it run) command if I've forgotten something. Or sometimes my connection times out (its pretty flakey at the minute) after 2 minutes and then I'm not sure what state it has left everything in, could it be caused by that?

At the point of this being "broken" running amplify status would say everything is up to date and as it should be yet my resolver was not setup as it should be. I've never edited a resolver manually until I found the issue and tried to fix it (which seems to have worked).

Steps to reproduce the behavior:

See attached two files, one called Sector which works (as it has all the DataStore stuff in it) and then the broken Staff model which doesn't mention the DataStore fields (I've renamed them as .txt files as I can't upload .vtl files).

staff-resolver.txt sector-resolver.txt

Winmerge screenshot showing some of the missing fields:

image

Now annoyingly I had fixed this last week but its just reoccurred today which is puzzling me. Team mate says they haven't pushed. I'm going to re-do it and see if I made any mistakes and keep an eye on it.

Expected behavior A clear and concise description of what you expected to happen.

The resolver if DataStore is enabled so inject in all the right template code to wire up mutations via DataStore. Ideally it should be able to recover from an unknown state (cancelled push or timeout) if it doesn't already.

What is Configured? If applicable, please provide what is configured for Amplify CLI:

amplify update api

Additional context Add any other context about the problem here.

_You can turn on the debug mode to provide more info for us by setting window.LOGLEVEL = 'DEBUG'; in your app.

amhinson commented 3 years ago

Thanks for the details @PeteDuncanson! 🙏 Could you also share the following info:

One additional thing to try is using amplify push --force. Since you mentioned that the backend resources could be in an incomplete state, this will make sure everything is created appropriately even if amplify status doesn't show any changes locally.

PeteDuncanson commented 3 years ago

Amplify v4.40.0

Package.json

{
  "name": "franchise-manager",
  "version": "0.1.0",
  "private": true,
  "main": "src/index.ts",
  "dependencies": {
    "@aws-amplify/ui-react": "^0.2.21",
    "@brainhubeu/react-file-input": "0.7.21",
    "@lourenci/react-kanban": "^2.1.0",
    "@tailwindcss/ui": "^0.6.2",
    "@tailwindui/react": "^0.1.1",
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.3.2",
    "@testing-library/user-event": "^7.1.2",
    "@types/javascript-time-ago": "^2.0.1",
    "@types/jest": "^26.0.13",
    "@types/node": "^14.6.3",
    "@types/react": "^16.9.49",
    "@types/react-dom": "^16.9.8",
    "@types/yup": "^0.29.7",
    "apollo-boost": "^0.4.9",
    "aws": "^0.0.3-2",
    "aws-amplify": "^3.3.1",
    "aws-amplify-react": "^4.2.5",
    "file-saver": "^2.0.2",
    "graphql": "^15.3.0",
    "history": "5",
    "react": "^16.13.1",
    "react-apollo": "^3.1.5",
    "react-dom": "^16.13.1",
    "react-icons": "^3.11.0",
    "react-router-dom": "^6.0.0-beta.0",
    "react-scripts": "3.4.3",
    "react-time-ago": "^6.2.1",
    "tailwind": "^4.0.0",
    "typescript": "^4.0.3",
    "yup": "^0.29.3"
  },
  "scripts": {
    "tailwind:css": "tailwind build src/styles/tailwind.src.css -c  tailwind.config.js -o src/styles/tailwind.css",
    "start": "yarn tailwind:css && react-scripts start",
    "build": "yarn tailwind:css && react-scripts build",
    "test": "yarn tailwind:css && react-scripts test",
    "eject": "yarn tailwind:css && react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "@ideal-postcodes/api-typings": "^2.0.0",
    "@ideal-postcodes/core-browser": "^1.3.0",
    "@types/reach__router": "^1.3.5",
    "@typescript-eslint/eslint-plugin": "^4.0.1",
    "@typescript-eslint/parser": "^4.0.1",
    "aws-sdk": "^2.765.0",
    "eslint": "6.6.0",
    "formik": "^2.1.5",
    "graphiql": "^1.0.5",
    "react-pagination-hook": "^0.0.1",
    "react-scripts": "3.4.3",
    "react-use": "^15.3.4",
    "tailwindcss": "^1.7.6",
    "vest": "^2.2.3"
  },
  "resolutions": {
    "**/@typescript-eslint/eslint-plugin": "^4.1.1",
    "**/@typescript-eslint/parser": "^4.1.1"
  }
}

graphql.schema (well the bits of it I mention, if you want/need the whole thing I can email it over)

type StaffMember
  @model
  @auth(
    rules: [
      { allow: groups, groups: ["admin"] }
      { allow: public, provider: apiKey }
    ]
  ) {
  id: ID!
  firstName: String!
  lastName: String!
  email: String
  phoneNumber: String
  roles: [String] 
  roundDirectionPreference: String 
  profilePictureUrl: String
}

type Sector
  @model
  @searchable
  @auth(
    rules: [
      { allow: groups, groups: ["admin"] }
      { allow: public, provider: apiKey }
    ]
  ) {
  id: ID!
  name: String!
  displayName: String!
  totalAreas: Int!
  totalCustomers: Int!
  totalRounds: Int!
}
amhinson commented 3 years ago

Ok thanks. A few follow-up questions:

PeteDuncanson commented 3 years ago
UPDATE_FAILED      storageImageStorage AWS::CloudFormation::Stack Wed Dec 23 2020 18:29:51 GMT+0000 (Greenwich Mean Time) Parameters: [authfranchisemanagerXXXXXUserPoolId, authuserPoolGroupsadminGroupRole] do not exist in the template

Not sure what that is or if its even related, another thing to google. I just want to fix actual problems for once :(

kaustavghosh06 commented 3 years ago

@PeteDuncanson Are you running amplify push or amplify api push? when you get the above failure?

PeteDuncanson commented 3 years ago

@kaustavghosh06 I'm running amplify push

I've removed storage to see if that helps and now its pushed fine annoyingly. So I guess I now need to add it all again and see if it does it again!

PeteDuncanson commented 3 years ago

On @Chia suggestion in the discord channel (https://discordapp.com/channels/705853757799399426/735987596462653461/791425772966641705) I tried disabling DataStore, pushing, then re-enabling and pushing again. I can report that the resolvers are still broken and I've no idea why.

They still don't have the DataStore fields needed to make them DataStore aware.

PeteDuncanson commented 3 years ago

I'm not at the point of either thinking my whole project is just corrupt somehow or amplify isn't the way to go. Either way I've lost so much time trying to fix these issues that shouldn't be issues rather than pushing this project forward. I've logged everything as I come across it as an issue so others can hopefully avoid these quirks and errors.

Its now Christmas Eve which means I've been working past midnight to try to get this sorted but I'm out of time, energy and effort. 2020 can do one.

akshbhu commented 3 years ago

Hi @PeteDuncanson

Can you try amplify api gql-compile command and check transform.conf.json file if its has conflict detection enabled for the project and also you can check resolvers contain _version field?

Amplify uses transform.conf.json to check if the project uses datastore and generate VTL code based on that before push.

PeteDuncanson commented 3 years ago

Hi @akshbhu,

First off can I say sorry for letting my frustrations get the better of me yesterday, I was just at the end off my tether, no excuse I should have just logged off. Apologies. You folks are all doing a great job day in, day out.

Secondly I've tried running amplify api gql-compile which said it had compiled successfully.

When search for the transform.conf.json file you mention I found 3 of them:

\src\amplify\#current-cloud-backend\api\MyApp\transform.conf.json - doesn't mention conflict detection \amplify\#current-cloud-backend\api\franchisemanager\transform.conf.json - mentions conflict detection \amplify\backend\api\franchisemanager\transform.conf.json - mentions conflict detection

{
    "Version": 5,
    "ElasticsearchWarning": true,
    "StackMapping": {
        "QueryjobCommentsByJobIDResolver": "JobComment"
    },
    "ResolverConfig": {
        "project": {
            "ConflictHandler": "AUTOMERGE",
            "ConflictDetection": "VERSION"
        }
    }
}

And when I try to update the API it only gives me the option to disable it so I'm assuming its switched "on":

image

Clicking through the resolvers within\amplify\backend\api\franchisemanager\build\resolvers

I can see that very few of them have the following _version code at the end of them (which is what I'm using to eye ball if they are "DataStore aware" or not, let me know if this is wrong):

image

I'm treating that missing as something wrong as when I try to save via the DataStore to a resolver that doesn't have that to the bottom I get the original error. If I manually add in the bits that are missing (see original opening message) then it works. But I'm worried why its not rolled out automatically and how it reverted?

I'm happy to manually fix them all up in my solution but I fear they will just get over-written.

Where too next?

akshbhu commented 3 years ago

Hi @PeteDuncanson

\src\amplify#current-cloud-backend\api\MyApp\transform.conf.json - doesn't mention conflict detection

I am assuming this file is present in another project as Amplify only support one API per project.

I can see that very few of them have the following _version code at the end of them (which is what I'm using to eye ball if they are "DataStore aware" or not, let me know if this is wrong):

This is not a way to check if your project is datastore enabled as it is possible some resolvers wont need _version field. it depends on the operation.

Also as you said manually adding the _version field in some resolvers solve the error , Can you mention those resolvers on to which you are adding these fields to manually to make them work?

PeteDuncanson commented 3 years ago

@akshbhu I've only been using my check for "DataStoreness" (my new word of the day) on the update resolvers. So updateSector has it, updateStaff doesn't. The updateSector one works and doesn't thrown an error, the updateStaff was has those fields missing and does throw the error mentioned in my opening comment. You can see a full diff of whats different in the opening comment but its just those last few lines that I've been using to quickly eye ball if a update resolve has DataStoreness or not.

I've assumed this is a safe check as DataStore needs _version to be sent to beable to do its DataStore magic to check we are updating the same record/entry we think we are, is it the same version. So if they aren't in the update resolvers then it can't do that or that is my understanding.

Regarding your final point, I'm adding to to the update resolvers that don't pass my simple check (ie do they mention the _version field where they should) if not then I cut and paste the missing bits in (seems to only be in two places per file). When I do that the error goes away...however after I slept it returned! So something I think must be over-writing it but I'm not sure what, how or why or how to stop it.

PeteDuncanson commented 3 years ago

A little update on this one. I've spent the afternoon manually going through all the Mutation update/delete resolvers I found in \amplify\backend\api\franchisemanager\build\resolvers and noted which ones seems to be "right" and which were missing bits. Oddly all the broken ones didnt' have any of the Authentication stuff at the top of them which the others did (again see the original two files in the opening description).

I tested each before I made any changes and then after. Each would through the error mentioned in the issue title, but when I edited it to include the DataStore bits and bobs it would work. To edit them I'm doing this manually in the AppSync Schema UI:

Search for "Mutation" to list all the update/delete resolvers

Edit the resolver and save to deploy it

Finally after I had them all done I did a amplify pull but I'm not sure if this is actually going to do anything and I wonder if on the next push if I'm going to lose all these edits?

Currently as it stands everything is working BUT:

So, any pointers on how I can ensure that these resolvers are "saved" somewhere so they are safe and working when I next push? I wondered if there was a way to force it to regenerate them? I've tried removing DataStore and re-adding but that didn't fix it so not sure how to "tickle" it to get it to get in a known state.

I could do the trick of editing the deployed zip file that will be up in S3 and cut and paste the new resolvers in there (I've got them saved in a backup folder), re-upload and then hope it will pull that down on the next push and sort itself out but I'm not sure if this is even a valid fix/hack?

PeteDuncanson commented 3 years ago

First full day back at work today (and a new country wide lockdown here in the UK too) and all the work I did over the weekend has reverted back to not being DataStore aware again. Its as if all my manual changes over the weekend have disappeared again.

I don't know what I'm doing wrong here or how to fix it.

Neither me or my work mate have done a push, we just left it "fixed" after my weekend work to get it working for us ready for today.

Any ideas or pointers?

amhinson commented 3 years ago

Transferring this to the CLI repo to get more eyes on it, as the issue doesn't appear to be related to the JS library anymore.

PeteDuncanson commented 3 years ago

So yesterday I managed to do a push and get the resolvers up in the cloud again. Result!

I cleared out all the resolvers I found in /amplify/backend/api/<MyApp>/resolvers as I don't think they are the "real" ones and talking to another dev we think that folder is used for over-writing generated resolvers should you need to (would love some confirmation on that).

Then I did a push and it worked and I had an afternoon of work that could be done.

Logging in today I'm back to the same error, the resolvers have all reverted in the cloud somehow, no one else has done a push. What gives?

I've got a theory but not sure if its based on fact or anything.

It worked yesterday when we pushed it up and while I was using it. Then we slept and today its broken again. Could it be that over-night AWS cleared out the App due to lack of interaction, sort of put it to sleep, then when we hit it again in the morning it hydrates it from somewhere? Could it be that where it hydrates it from has the broken resolves in it? If so how to fix that or check it? Would it be a zip up in S3 somewhere I can check or delete?

A push today has fixed it again...but then I fear that tomorrow it will have reverted again. How best to just clear out this glitch?

PeteDuncanson commented 3 years ago

Think I've found the issue here. Our CI was redeploying from git but the fix of removing the custom resolvers mentioned above hadn't been pushed up to github yet. My team mate did a git push with other code in it that triggered the CI and over-wrote my fix that I'd manually deployed via amplify push yesterday.

I've since pushed up my fixes to git and the CI has rebuilt again and the resolvers are now all working again. Result!

I'll await tomorrow to double check but if its all still working I'll close this one.

For those following along the cause was having copies of the resolvers in this folder ``/amplify/backend/api//resolvers``` which were out of date and seem to over-write the generated resolvers from Amplify.

akshbhu commented 3 years ago

@PeteDuncanson Good to know that it is working today for you 👍

I cleared out all the resolvers I found in /amplify/backend/api//resolvers as I don't think they are the "real" ones and talking to another dev we think that folder is used for over-writing generated resolvers should you need to (would love some confirmation on that).

Thats true , If you have any resolvers present in the /amplify/backend/api/<MyApp>/resolvers , those resolvers wont be touched and direclty copied to cloud as these resolvers contains manual changes and amplify doesnt overwrite on them. This way customers can have custom resolvers or their own implemented resolvers.

I guess this is the case for you, it keeps on overiding for you as a stale resolver file might be present in /amplify/backend/api/<MyApp>/resolvers and keep getting pushed when you are doing amplify push.

Let me know if this answer your question.

PeteDuncanson commented 3 years ago

@akshbhu I've been working on it all day today and pushing git and no problems to report. I think we have found our culprit!

Thanks for everyone's help on this on especially Chai from the Discord channel who really dug deep to help me out.

Consider this one closed.

github-actions[bot] commented 3 years ago

This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.

Looking for a help forum? We recommend joining the Amplify Community Discord server *-help channels for those types of questions.