graphqlaws-appsyncaws-appsync-resolver

Empty data in AWS AppSync GraphQL subscription event


I have an application that uses a GraphQL API, provided by the AWS AppSync service. It uses GraphQL subscriptions to send messages between different clients in near real time. There is a mutation pushItems that's configured with a resolver, which has a 'none' data source and forwards the request data unmodified to the subscription onItemChange.

The app hasn't been used for a couple of years, and now when I attempt to trigger a subscription event, I get an error on the subscribed client. Previously this worked without issues.

{
  "data": {
    "onItemChange": null
  },
  "errors": [
    {
      "message": "Cannot return null for non-nullable type: 'ID' within parent 'Item' (/onItemChange/id)",
      "path": [
        "onItemChange",
        "id"
      ]
    }
  ]
}

The error message suggests that the property id within the Item object is null, however when I send a mutation from the AWS AppSync web console with a hard-coded string for the item ID, I still get the same issue, even though the mutation response contains the correct data that should be forwarded to the subscribed client.

I've created a minimal configuration in AWS AppSync to reproduce the issue, which is detailed below. Is it possible that the AppSync service has changed the way it handles subscription data in the last few years?

GraphQL schema

schema {
  query: Query
  mutation: Mutation
  subscription: Subscription
}

type Query {
  getItem(id: ID!): Item
}

type Mutation {
  pushItems(
    items: [ItemInput]
  ): [Item]}

type Subscription {
  onItemChange: Item
  @aws_subscribe(
    mutations: [
    "pushItems"
    ]
  )
}

type Item {
  id: ID!
}

input ItemInput {
  id: ID!
}

Resolver mappings for mutation pushItems

Request:

{
  "version" : "2017-02-28",
  "payload": $util.toJson($context.arguments.items)
}

Response:

$util.toJson($context.result)

Example queries

The following queries can be used to reproduce the issue in the AWS AppSync web console. First, subscribe to onItemChange:

subscription MySubscription {
  onItemChange {
    id
  }
}

Then (in a different browser tab) send some data to pushItems:

mutation MyMutation {
  pushItems(items: [{id: "foo"}]) {
    id
  }
}

Solution

  • You are returning Set of items in the mutation so you should update subscription return type to [Item]

    type Subscription {
        onItemChange: [Item]  <--- HERE
            @aws_subscribe(mutations: ["pushItems"])
    }