6
votes

I'm using react native and aws amplify to interface with graphQL. However when making this mutation I receive the error ""Variable 'input' has coerced Null value for NonNull type 'ID!'".

addStudent = async (classData) => {
    try {
    let user = await Auth.currentAuthenticatedUser();
    const emailAttribute = user.attributes.email;
    const studentObj = {
      name: this.state.studentName,
      email: emailAttribute,
      class: classData.id,
    }
    await API.graphql(graphqlOperation(mutations.createStudent, { input: studentObj }));
} catch (err) {
    console.error(err);
}
}

Here is my schema:

type Class @model @auth(rules: [{ allow: owner, queries: null}]) {
id: ID!
name: String!
password: String!
email: String!
students: [Student] @connection(name: "ClassStudents")
}

type Student @model @auth(rules: [{ allow: owner, queries: null}]) {
id: ID!
name: String!
email: String!
class: Class! @connection(name: "ClassStudents")
attendance: [Attendance] @connection(name: "StudentAttendance")
}

And here is the mutation I'm trying to call that AWS generated:

export const createStudent = `mutation CreateStudent($input: CreateStudentInput!) {
  createStudent(input: $input) {
id
name
email
class {
  id
  name
  password
  email
  students {
    nextToken
  }
}
attendance {
  items {
    id
    date
  }
  nextToken
}
}
}
`;

I have tried solutions from similar questions such as changing the syntax of the mutator argument but the error persists. Any idea of how to solve this?

2
no id property defined in input object (mutation parameter) studentObj - xadm
@xadm When I call the mutator createClass i did not have to pass in an id value. In the amplify documentation they never pass in a value for an id. - RoyGBivJr
make id nullable in CreateStudentInput - xadm

2 Answers

0
votes

It isn't the student id that is the problem. It has to do with this connection:

class: Class! @connection(name: "ClassStudents")

The Class item is a GraphQL connected type. It isn't an id. You probably have a column that is something like: classStudentId or studentClassId. I am still learning exactly how this column gets auto-created in AppSync, but it is how AppSync manages the connection in DynamoDB. You have to specify that id column, not class:.

eg:

addStudent = async (classData) => {
  try {
    let user = await Auth.currentAuthenticatedUser();
    const emailAttribute = user.attributes.email;
    const studentObj = {
      name: this.state.studentName,
      email: emailAttribute,
      studentClassId: classData.id,
    }
    await API.graphql(graphqlOperation(mutations.createStudent, { input: studentObj }));
  } catch (err) {
    console.error(err);
  }
}

My Example

As an example, I can share the problem I just worked through that led me here while I was trying to fix it:

Schema:

type Message @model
  @auth(
    rules: [
      { allow: owner, operations: [create, read, update, delete] }
      { allow: groups, groups: ["everyone"], operations: [read] }
    ]
  )
  @key(fields: ["associationId", "createdAt"]) {
  id: ID!
  associationId: String!
  content: String!
  createdAt: AWSDateTime!
  author: User! @connection(name: "UserMessages", keyField: "owner")
}

Mutation:

export const createMessage = /* GraphQL */ `
  mutation CreateMessage(
    $input: CreateMessageInput!
    $condition: ModelMessageConditionInput
  ) {
    createMessage(input: $input, condition: $condition) {
      id
      associationId
      content
      createdAt
      owner
      author {
        id
        firstName
        lastName
        email
        phone
        avatar {
          bucket
          region
          key
        }
      }
    }
  }
`;

Normally, I could create a message like this:

const submitData = {
  associationId: association.id,
  content: fields.message,
}
await API.graphql(graphqlOperation(CreateMessage, { input: submitData }))

Amplify will get the current user id from Cognito (using auth) and will create a unique id for me.

However, since I specified that owner would be the connection key field, I now have to add the user's id to the owner column manually unfortunately, I can't leave it empty and rely on Amplify anymore.

I have made owner a DynamoDB requirement to connect to the User table instead of just a Cognito connection field that Amplify can use. I could specify the user id in a separate column like authorId, but since the User table uses the Cognito id anyway, I am trying to condense these into one column... So now I have to do this, or I get the same error you were getting:

const submitData = {
  associationId: association.id,
  content: fields.message,
  owner: user.id,
}
await API.graphql(graphqlOperation(CreateMessage, { input: submitData }))

Your situation is obviously different, but you need to find out how it is actually storing the Class id and manually specify it. Or you can force it to use a key field that you want like classId, but you can't use the connection item itself. That isn't how it is stored.

-3
votes

Yes, I think the first line of the mutation should look like this;

export const createStudent = `mutation CreateStudent($input: ID!)