amplify-js: DataStore.save not sending correct input data to graphQL endpoint

Before opening, please confirm:

JavaScript Framework

Vue

Amplify APIs

GraphQL API, DataStore

Amplify Categories

api

Environment information

# Put output below this line
    "@aws-amplify/cli": "^11.0.3",
    "@aws-amplify/core": "^5.1.8",
    "@aws-amplify/datastore": "^4.1.7",
    "aws-amplify": "^5.1.1",

Describe the bug

Note, that I did find this ticket but it was closed without conclusion.

I’m calling DataStore.save on this model:

type LevelInfo @model @auth(rules: [
    { allow: groups, groupsField: "tenant", operations: [read, update] },
    { allow: owner }
]) {
  id: ID!
  tenant: String @default(value: "admin")
  name: String!
  order: Int!
  people: [Person] @hasMany
}

Generated code as

type LazyLevelInfo = {
  readonly [__modelMeta__]: {
    identifier: ManagedIdentifier<LevelInfo, 'id'>;
    readOnlyFields: 'createdAt' | 'updatedAt';
  };
  readonly id: string;
  readonly tenant?: string | null;
  readonly name: string;
  readonly order: number;
  readonly people: AsyncCollection<Person>;
  readonly createdAt?: string | null;
  readonly updatedAt?: string | null;
}

It has this value:

{
  _deleted: undefined
  _lastChangedAt: undefined
  _version: undefined
  createdAt: null
  id: '871ba18a-b6bf-42b8-ad20-1627a5bce514'
  name: 'New Level'
  order: 2
  people: ƒ ()
  tenant: 'xxx'
  updatedAt: null
}

Log output is below

Expected behavior

DataStore formats the POST to GraphQL properly and the Item is saved to DynamoDB since it does contain both required fields. If there is an error, it throws an error (not as worried about this part since it’s a known issue with how DataStore works), (note that in logs it says DataStore - Mutation sent successfully with authMode: AMAZON_COGNITO_USER_POOLS) despite it failing.

Reproduction steps

  1. Detailed instructions above

Code Snippet

// Put your code below this line.
  const lvl = new LevelInfo({
    name: 'New Level',
    order: 1,
  })
  DataStore.save(lvl)

Log output

// Put your logs below this line
[WARN] 59:18.506 DataStore {recoverySuggestion: 'Ensure app code is up to date, auth dir…thub.com/aws-amplify/amplify-js/issues', localModel: {…}, message: 'Variable 'input' has coerced Null value for NonNull type 'String!'', operation: 'Create', errorType: 'BadRecord', …}

// Network Payload is incorrectly created (missing name and order)
query: "mutation operation($input: CreateLevelInfoInput!) {\n  createLevelInfo(input: $input) {\n    id\n    tenant\n    name\n    order\n    createdAt\n    updatedAt\n    owner\n    _version\n    _lastChangedAt\n    _deleted\n  }\n}\n"
variables: {input: {id: "3cdbe3e5-c8fe-4fa0-a6e6-ad688ec0711d", tenant: "tekkr.io"}}
input:{id: "3cdbe3e5-c8fe-4fa0-a6e6-ad688ec0711d", tenant: "tekkr.io"}

// Complete amplify logs
[DEBUG] 38:39.424 DataStore - Attempting mutation with authMode: AMAZON_COGNITO_USER_POOLS
ConsoleLogger.js:87 [DEBUG] 38:39.424 Util -  attempt #1 with this vars: ["LevelInfo","Create","{\"tenant\":\"tekkr.io\",\"id\":\"71cc288b-6a49-420d-9291-6d1a661d7d0f\"}","{}",null,null,{"data":"{\"tenant\":\"tekkr.io\",\"id\":\"71cc288b-6a49-420d-9291-6d1a661d7d0f\"}","modelId":"71cc288b-6a49-420d-9291-6d1a661d7d0f","model":"LevelInfo","operation":"Create","condition":"{}","id":"01GXX6HKZEA9ZFCVSG4MGN23X1"}]
ConsoleLogger.js:87 [DEBUG] 38:39.424 AuthClass - Getting current session
ConsoleLogger.js:99 [DEBUG] 38:39.425 AuthClass - Succeed to get the user session CognitoUserSession {idToken: CognitoIdToken, refreshToken: CognitoRefreshToken, accessToken: CognitoAccessToken, clockDrift: -1}
ConsoleLogger.js:99 [DEBUG] 38:39.425 AuthClass - Succeed to get the user session CognitoUserSession {idToken: CognitoIdToken, refreshToken: CognitoRefreshToken, accessToken: CognitoAccessToken, clockDrift: -1}
ConsoleLogger.js:99 [DEBUG] 38:39.425 RestClient - POST https://eunhffv72raqlgolbhj2axas54.appsync-api.eu-central-1.amazonaws.com/graphql
ConsoleLogger.js:87 [DEBUG] 38:39.622 DataStore - Mutation sent successfully with authMode: AMAZON_COGNITO_USER_POOLS
ConsoleLogger.js:87 [DEBUG] 38:39.622 DataStore - done retrying

aws-exports.js


const awsmobile = {
    "aws_project_region": "eu-central-1",
    "aws_appsync_graphqlEndpoint": "https://eunhffv72raqlgolbhj2axas54.appsync-api.eu-central-1.amazonaws.com/graphql",
    "aws_appsync_region": "eu-central-1",
    "aws_appsync_authenticationType": "AMAZON_COGNITO_USER_POOLS",
    "aws_cognito_identity_pool_id": "eu-central-1:10815ea4-dd8c-4f62-8d6a-0a1e7315d3d1",
    "aws_cognito_region": "eu-central-1",
    "aws_user_pools_id": "eu-central-1_jYr6oXxWw",
    "aws_user_pools_web_client_id": "7kv2rsa14um3g3l2jlqr10ajuo",
    "oauth": {
...
    },
    "federationTarget": "COGNITO_USER_AND_IDENTITY_POOLS",
    "aws_cognito_username_attributes": [
        "EMAIL"
    ],
    "aws_cognito_social_providers": [
        "GOOGLE"
    ],
    "aws_cognito_signup_attributes": [
        "EMAIL"
    ],
    "aws_cognito_mfa_configuration": "OPTIONAL",
    "aws_cognito_mfa_types": [
        "SMS"
    ],
    "aws_cognito_password_protection_settings": {
        "passwordPolicyMinLength": 8,
        "passwordPolicyCharacters": []
    },
    "aws_cognito_verification_mechanisms": [
        "EMAIL"
    ],
    "aws_user_files_s3_bucket": "**",
    "aws_user_files_s3_bucket_region": "eu-central-1"
};

Manual configuration

No response

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 34 (16 by maintainers)

Most upvoted comments

Hi @svidgen,

I encountered the same issue with the latest version and downgrading to 5.0.24 works for me.

After some troubleshooting, I was able to easily replicate the issue. It seems that the #11171 fix doesn’t consider the following scenario:

A new object is created such as new Todo({...}) but not imediately saved. Later on, use Todo.copyOf() to update some of the non-null fields and run DataStore.save(). It appears that all these non-updated fields are being removed and displayed as ‘undefined’ in the localModel. Therefore, the create mutation fails since “Null value for NonNull type”

Replication code

function App() {

  const todoRef = useRef();

  useEffect(() => {
    todoRef.current = new Todo({
      f1: 'f1',
      f2: 'f2',
      f3: 'f3',
      f4: 'f4',
      f5: 'f5',
      f6: 'f6'
    })
  }, []);

  const testClicked = () => {
    const toSave = Todo.copyOf(todoRef.current, updated => {
      updated.f1 = 'updated f1';
    });

    console.log(toSave);

    DataStore.save(toSave);
  }

  return (
    <div className="App">
      <button onClick={testClicked}>Test</button>
    </div>
  );
}
Screenshot 2023-07-30 at 10 08 23 am

Sure. Happy to help. I’ll schedule something next week.