fix: make sendError payload format respect WebSocket subprotocol - #1255
fix: make sendError payload format respect WebSocket subprotocol#1255tsushanth wants to merge 3 commits into
Conversation
mcollina
left a comment
There was a problem hiding this comment.
Thanks for opening a PR! Can you please add a unit test?
Also update existing graphql-ws tests to expect a single error object (not wrapped in array) per the subscriptions-transport-ws spec.
|
Added two unit tests in
Running the full test suite also surfaced three existing tests that were asserting the old (broken) array format for |
|
Hi @mcollina — the unit tests you asked for are in
Also updated three existing tests in |
|
The spec direction here looks right to me — subscriptions-transport-ws does want a single error object, and graphql-transport-ws wants the array. But I think the protocol check needs to use the resolved protocol rather than the raw one, or the change lands inconsistently.
So on a server configured with I applied the diff to 16.9.0 and drove two clients against one server (
Minimal fix, since the signals object is already exported: const { GRAPHQL_WS_PROTOCOL_SIGNALS } = require('./subscription-protocol')
sendError (err, id) {
const convertedError = toGraphQLError(err)
const payload = this.protocolMessageTypes === GRAPHQL_WS_PROTOCOL_SIGNALS
? convertedError
: [convertedError]
this.sendMessage(this.protocolMessageTypes.GQL_ERROR, id, payload)
}That reuses the resolution already done in the constructor, so it stays correct however Separately on versioning: this changes an observable wire format for clients that have been parsing |
|
@tsushanth this is a test that shows the edge case Add it to |
|
Fixed in the latest push — switched from Also added your exact test case (the one you posted above) to |
|
Friendly ping — this has been approved by @mcollina for a week now and CI is green. Happy to rebase or make any changes if needed before merge. |
|
This is semver-major. I'll land it whenever we cut a new major. |
Problem
sendErrorinlib/subscription-connection.jsunconditionally wraps the error in an array:This is correct for the
graphql-transport-wsprotocol (the newer spec), but breaks clients using the legacysubscriptions-transport-wsprotocol. In mercurius/Fastify, that legacy protocol is identified bysocket.protocol === 'graphql-ws'— and it expects a single error object as the payload, not an array.Sending an array to a
subscriptions-transport-wsclient causes the client to fail to parse the error, surfacing as an unhandled error or silent failure rather than a proper GraphQL error.Fix
The active subprotocol is already available on
this.socket.protocoland is used elsewhere in the same class for protocol-branching logic. The fix is a one-line conditional:'graphql-ws'→ legacysubscriptions-transport-ws→ single error object'graphql-transport-ws') → newer spec → arrayCloses #1132