GraphQLTransportWSHandler sends invalid errors message breaking `graphql-ws` clients on error (should be an array)
kevinvalk opened this issue · comments
Lately I switched over to fully using the GraphQLTransportWSHandler for everything (including mutations and queries). However, I am receiving the following error on the client ("graphql-ws": "^5.11.2",
).
index.ts:43 Error: "error" message expects the 'payload' property to be an array of GraphQL errors, but got {"message":".......","locations":[{"line":1,"column":36}],"extensions":{"exception":null}}
at validateMessage (common.mjs:128:23)
at parseMessage (common.mjs:168:12)
at socket2.onmessage (client.mjs:202:37)
After checking graphql-ws
source code and protocol specification I think Apollo is not sending errors correctly:
https://github.com/enisdenjo/graphql-ws/blob/fbb763a662802a6a2584b0cbeb9cf1bde38158e0/src/utils.ts#L57-L66
https://github.com/enisdenjo/graphql-ws/blob/fbb763a662802a6a2584b0cbeb9cf1bde38158e0/PROTOCOL.md#error
The client expects an array of errors, but instead Apollo only sends a single error?
ariadne/ariadne/asgi/handlers/graphql_transport_ws.py
Lines 318 to 332 in 3218cff
ariadne/ariadne/asgi/handlers/graphql_transport_ws.py
Lines 368 to 379 in 3218cff
I'll mark this as a bug and put this on my radar for next release.
I only got to test this just now, but @rafalp the fix is not completely according spec and will still throw errors:
GraphQL websocket error: Error: "error" message expects the 'payload' property to be an array of GraphQL errors, but got [{"errors":[{"message":"Unknown argument 'id' on field 'Mutation.test'.","locations":[{"line":2,"column":20}],"extensions":{"exception":null}}]}]
{
"type": "error",
"id": "c243e373-4048-4108-a8d5-d5a23ed8e796",
"payload": [
{
"errors": [
{
"message": "Unknown argument 'id' on field 'Mutation.test'.",
"locations": [
{
"line": 2,
"column": 20
}
],
"extensions": {
"exception": null
}
}
]
}
]
}
The spec mentions that when type == 'error'
the payload is directly a list of errors, while currently it is a list of objects that contains the "errors" key with a list of errors.
import { GraphQLError } from 'graphql';
interface ErrorMessage {
id: '<unique-operation-id>';
type: 'error';
payload: GraphQLError[];
}
Reopening this
If I understand the spec right, if there's an error, instead of NEXT
we should send ERROR
message, because this protocol is not supporting partialy correct results?
It seems to me that there are three places in GraphQLTransportWSHandler
where errors can be returned to the client, and neither of those can create the error response you are mentioning:
type
is ERROR
and payload
is list of error objects, not {"errors": [...]}
. Looks okay.
type
is ERROR
and payload
is a list of result responses. Looks like this is the culprit. But I'll need further study.
Third place is where NEXT
is returned with payload.errors
instead of data:
I can reproduce this. This error only occurs for query
and mutation
operations sent to GraphQL Transport WS.
I've released 0.22 beta 1 with the fix.