-
Actual BehaviourCalling a subscription whose backend resolver errors out unfolds into this: import { WebSocket } from 'ws';
import { createClient as createGqlWsClient } from 'graphql-ws';
const gqlWsClient = createGqlWsClient({
url: `ws://localhost:4000`,
webSocketImpl: WebSocket,
});
const subscriptionIter = gqlWsClient.iterate({
query: `
subscription {
myErroringSubscription
}`,
});
try {
await subscriptionIter.next();
} catch (err) {
err; // an instance of `CloseEvent`
err.code; // 4500
err.type; // 'close'
err.reason; // 'Oh bummer...'
// and some other technical properties...
}
/*
1. The erroring field resulted the subscription iterable throwing out altogether
2. What's thrown is a `CloseEvent` with some technical data, which only carries the error text message thrown from the resolver - no access to any other standard GraphQL error properties and `extensions` in particular.
*/ On the other hand, calling a query whose backend resolver errors out ends up in: import { WebSocket } from 'ws';
import { createClient as createGqlWsClient } from 'graphql-ws';
const gqlWsClient = createGqlWsClient({
url: `ws://localhost:4000`,
webSocketImpl: WebSocket,
});
const queryIter = gqlWsClient.iterate({
query: `
query {
myErroringQuery
}`,
});
const next = await queryIter.next();
next.value;
/* {
"data": null,
"errors": [
{
"message": "Oh bummer...",
"locations": [
{
"line": 3,
"column": 7
}
],
"path": [
"myErroringQuery"
],
"extensions": {
"foo": "bar"
}
}
]
} */
/*
1. The result iterable did not throw an error and just yielded a value.
2. The yielded value shows what looks like the original response you'd expect, including all the standard error properties and the backend-customized `extensions` in particular.
*/ Expected BehaviourI expected that Further InformationThe exact GraphQL API setup code that produces all which was describedSample setup for a GraphQL API which holds an erroring query operation and an equivalent erroring subscription: import { WebSocket, WebSocketServer } from 'ws';
import { useServer } from 'graphql-ws/lib/use/ws';
import { makeExecutableSchema } from '@graphql-tools/schema';
import { GraphQLError } from 'graphql';
const schema = makeExecutableSchema({
typeDefs: `
type Query {
myErroringQuery: String!
}
type Subscription {
myErroringSubscription: String!
}
`,
resolvers: {
Query: {
myErroringQuery: async () => {
throw new GraphQLError('Oh bummer...', { extensions: { foo: 'bar' } });
},
},
Subscription: {
myErroringSubscription: {
subscribe: async function* () {
throw new GraphQLError('Oh bummer...', { extensions: { foo: 'bar' } });
},
},
},
},
});
useServer({ schema }, new WebSocketServer({ port: 4000 })); The goal is to have errors returned from the GraphQL backend convey extra information and context populated in the However, it appeared for me that there's currently a difference in how erroring is treated and propagated when it is resulting from calling a Debug infoIn case it helps to pin down on the source of the problem - it appears that if we'd take the same subscription resolver from the setup code above and just change the resolvers: {
Query: {
myErroringQuery: async () => {
throw new GraphQLError('Oh bummer...', { extensions: { foo: 'bar' } });
},
},
Subscription: {
myErroringSubscription: {
- subscribe: async function* () {
+ subscribe: async () => {
throw new GraphQLError('Oh bummer...', { extensions: { foo: 'bar' } });
},
},
},
}, Thanks for any help!!! 💛 |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
That is because the resolvers in graphql-js schema catch errors and return them in the execution result. While, on the other hand, throwing from If an error is thrown from anywhere on a graphql-ws powered backend - it results in the server closing the connection. It does not matter if the client is subscribing or querying. See this discussion and how to remidy the |
Beta Was this translation helpful? Give feedback.
That is because the resolvers in graphql-js schema catch errors and return them in the execution result. While, on the other hand, throwing from
subscribe
in a GraphQL schema will not catch and will bubble the error instead.If an error is thrown from anywhere on a graphql-ws powered backend - it results in the server closing the connection. It does not matter if the client is subscribing or querying.
See this discussion and how to remidy the
subscribe
function.