-
Notifications
You must be signed in to change notification settings - Fork 2k
Closed
Closed
Copy link
Description
Hello,
we have a problem when throwing a GraphQLError from GraphQLScalarType in the new apollo v4. Before (in v3) it properly propagated the error into formatError hook but now it always changes its extensions.code to BAD_USER_INPUT and removes all additional fields.
This is happening only on errors thrown from GraphQLScalarType (e.g. errors from mutation/query resolvers work just fine) and only when we define GQL schema using GraphQLSchema. I tried this example where the schema is defined using typeDefs and resolvers keys and it also worked.
Here is the code where you can reproduce the error.
const { unwrapResolverError } = require('@apollo/server/errors');
const { ApolloServer } = require('@apollo/server');
const { startStandaloneServer } = require('@apollo/server/standalone');
const { GraphQLScalarType, GraphQLError } = require('graphql');
const { GraphQLSchema, GraphQLObjectType, GraphQLInputObjectType } = require('graphql');
const ColorScalarField = new GraphQLScalarType({
name: 'ScalarField',
serialize: (value) => value,
parseValue: () => {
console.log("Serializing")
throw new GraphQLError('Scalar field custom error', {
extensions: { code: 'CUSTOM_ERROR_CODE', extraErrorField: 123 },
});
},
parseValue: () => {
console.log("Parsing value")
throw new GraphQLError('Scalar field custom error', {
extensions: { code: 'CUSTOM_ERROR_CODE', extraErrorField: 123 },
});
},
parseLiteral: () => {
console.log("Parsing literal")
throw new GraphQLError('Scalar field custom error', {
extensions: { code: 'CUSTOM_ERROR_CODE', extraErrorField: 123 },
});
},
});
const ItemType = new GraphQLObjectType({
name: 'item',
fields: () => ({
color: {
type: ColorScalarField,
},
}),
});
const ItemUpdateType = new GraphQLInputObjectType({
name: 'ItemUpdate',
fields: () => ({
color: {
type: ColorScalarField,
},
}),
});
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: () => ({
item: {
type: ItemType,
description: 'Fetch the logged in user.',
resolve: () => {},
}
}),
}),
mutation: new GraphQLObjectType({
name: 'Mutation',
fields: () => ({
itemUpdate: {
name: 'itemUpdate',
args: {
input: {
type: ItemUpdateType,
},
},
type: ItemType,
resolve: () => {},
}
}),
}),
});
const server = new ApolloServer({
schema,
debug: true,
formatError: (err, err2) => {
console.log("FORMAT ERROR:", err, err2)
console.log("UNWRAPPED ERROR:", unwrapResolverError(err), unwrapResolverError(err2))
return { err: 123 };
}
});
(async () => {
const { url } = await startStandaloneServer(server);
console.log(`🚀 Server listening at: ${url}`);
const response = await server.executeOperation({
query: `
mutation itemUpdate($input: ItemUpdate!) {
itemUpdate(input: $input) {
color
}
}
`,
variables: {
input: {
color: 'red',
},
},
});
console.log(response.body.singleResult.data)
console.log(response.body.singleResult.errors)
})();And here is the output.
Parsing value
FORMAT ERROR: {
message: 'Variable "$input" got invalid value "red" at "input.color"; Scalar field custom error',
locations: [ { line: 2, column: 27 } ],
extensions: {
code: 'BAD_USER_INPUT',
stacktrace: [
'GraphQLError: Variable "$input" got invalid value "red" at "input.color"; Scalar field custom error',
' at /test/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/values.js:147:11',
' at coerceInputValueImpl (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/utilities/coerceInputValue.js:154:9)',
' at coerceInputValueImpl (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/utilities/coerceInputValue.js:117:34)',
' at coerceInputValueImpl (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/utilities/coerceInputValue.js:49:14)',
' at coerceInputValue (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/utilities/coerceInputValue.js:32:10)',
' at coerceVariableValues (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/values.js:132:69)',
' at getVariableValues (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/values.js:45:21)',
' at buildExecutionContext (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/execute.js:280:63)',
' at execute (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/execute.js:116:22)',
' at executeIncrementally (/test/node_modules/.pnpm/@[email protected][email protected]/node_modules/@apollo/server/dist/cjs/incrementalDeliveryPolyfill.js:47:34)'
]
}
} GraphQLError: Variable "$input" got invalid value "red" at "input.color"; Scalar field custom error
at /test/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/values.js:147:11
at coerceInputValueImpl (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/utilities/coerceInputValue.js:154:9)
at coerceInputValueImpl (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/utilities/coerceInputValue.js:117:34)
at coerceInputValueImpl (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/utilities/coerceInputValue.js:49:14)
at coerceInputValue (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/utilities/coerceInputValue.js:32:10)
at coerceVariableValues (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/values.js:132:69)
at getVariableValues (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/values.js:45:21)
at buildExecutionContext (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/execute.js:280:63)
at execute (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/execute.js:116:22)
at executeIncrementally (/test/node_modules/.pnpm/@[email protected][email protected]/node_modules/@apollo/server/dist/cjs/incrementalDeliveryPolyfill.js:47:34) {
path: undefined,
locations: [ { line: 2, column: 27 } ],
extensions: { code: 'BAD_USER_INPUT' }
}
UNWRAPPED ERROR: {
message: 'Variable "$input" got invalid value "red" at "input.color"; Scalar field custom error',
locations: [ { line: 2, column: 27 } ],
extensions: {
code: 'BAD_USER_INPUT',
stacktrace: [
'GraphQLError: Variable "$input" got invalid value "red" at "input.color"; Scalar field custom error',
' at /test/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/values.js:147:11',
' at coerceInputValueImpl (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/utilities/coerceInputValue.js:154:9)',
' at coerceInputValueImpl (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/utilities/coerceInputValue.js:117:34)',
' at coerceInputValueImpl (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/utilities/coerceInputValue.js:49:14)',
' at coerceInputValue (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/utilities/coerceInputValue.js:32:10)',
' at coerceVariableValues (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/values.js:132:69)',
' at getVariableValues (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/values.js:45:21)',
' at buildExecutionContext (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/execute.js:280:63)',
' at execute (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/execute.js:116:22)',
' at executeIncrementally (/test/node_modules/.pnpm/@[email protected][email protected]/node_modules/@apollo/server/dist/cjs/incrementalDeliveryPolyfill.js:47:34)'
]
}
} GraphQLError: Variable "$input" got invalid value "red" at "input.color"; Scalar field custom error
at /test/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/values.js:147:11
at coerceInputValueImpl (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/utilities/coerceInputValue.js:154:9)
at coerceInputValueImpl (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/utilities/coerceInputValue.js:117:34)
at coerceInputValueImpl (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/utilities/coerceInputValue.js:49:14)
at coerceInputValue (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/utilities/coerceInputValue.js:32:10)
at coerceVariableValues (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/values.js:132:69)
at getVariableValues (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/values.js:45:21)
at buildExecutionContext (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/execute.js:280:63)
at execute (/test/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/execute.js:116:22)
at executeIncrementally (/test/node_modules/.pnpm/@[email protected][email protected]/node_modules/@apollo/server/dist/cjs/incrementalDeliveryPolyfill.js:47:34) {
path: undefined,
locations: [ { line: 2, column: 27 } ],
extensions: { code: 'BAD_USER_INPUT' }
}
undefined
[ { err: 123 } ]
I would expect the error received in formatError hook to have extensions.code === 'CUSTOM_ERROR_CODE' and extensions.extraErrorField === 123.
Is there anything we missed? Thank you for any help.
Metadata
Metadata
Assignees
Labels
No labels