You can find code example for this chapter here.
Notice that the subscription looks like a query as it has a type in the schema and the subscription itself can define what fields it needs. This fits into the GraphQL world: clients define the data they need and they only get that.
But there is a catch here. The above subscription was triggered by this mutation:
mutation MyMutation {
addTodo(name: "todo1") {
created
id
name
}
}
But notice what happens for this one:
mutation MyMutation {
addTodo(name: "todo2") {
id
name
}
}
This produces a rather strange error on the subscription's side:
{
"data": {
"newTodo": null
},
"errors": [
{
"message": "Cannot return null for non-nullable type: 'AWSDateTime' within parent 'Todo' (/newTodo/created)",
"path": [
"newTodo",
"created"
]
}
]
}
Why this error?
The schema defines the created
as a required field:
type Todo {
id: ID!
name: String!
created: AWSDateTime!
}
It turns out that AppSync only fills the subscription events with the fields that the mutation defined. And since the mutation did not specify the created
it is null. And that violates the schema, so the subscription returns an error.
This is a common source of confusion when working with subscriptions as it's not obvious what causes this problem. Also, this means how the mutation is called can break the subscriptions. And since mutations come from the clients, there is no enforcement on the backend-side. A change in one client can break another one.
Another problem is that it's not obvious what fields are really available for a subscription. The schema helps with the possible fields but it is ultimately decided by the mutations.
We'll discuss a solution in the Notify subscription pattern chapter.