fix: invalid queries return their real error code #100
+253
−27
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
Invalid queries came back as
INTERNAL_SERVER_ERRORwith the message "Internal server error". They now get their real code, for exampleGRAPHQL_VALIDATION_FAILED, while unexpected errors in resolvers are still hidden.Closes #93
Cause
Since
84116e6,formatErrortreated every error that Apollo wraps in another error (original !== error) as unknown and hid it. Apollo wraps its own errors too. I ranformatErroragainst a real Apollo Server (5.5.1) and found that more than the issue lists was hidden:INTERNAL_SERVER_ERRORGRAPHQL_VALIDATION_FAILEDINTERNAL_SERVER_ERRORGRAPHQL_PARSE_FAILEDINTERNAL_SERVER_ERRORBAD_USER_INPUToperationNameINTERNAL_SERVER_ERROROPERATION_RESOLUTION_FAILUREINTERNAL_SERVER_ERROR(hidden)The old unit test built its error without
originalError, which is not how Apollo sends them, so it passed while the server test failed.What is in it
formatErrordecides in three steps: (1) our own errors keep their code, (2) an error with one of Apollo's client error codes is let through with its message, (3) everything else is hidden and logged, as before.APOLLO_CLIENT_ERROR_CODESlists every code by name (ApolloServerErrorCode.*), with a comment on each.INTERNAL_SERVER_ERRORis left out on purpose.docs/API.md: the error table and a short text about what is let through and what is hidden.docs/AI_USAGE.md: a new section.Choices
INTERNAL_SERVER_ERROR?ApolloServerErrorCodepath) instead of by code?extensions.code.Testing
npx vitest run: 27 files, 268 tests passed, none skipped, against a throwaway PostgreSQL 18 with the seeded catalog.rejects a query that is too deep, and accepts one at the limitinserver.test.tsfails ondev(INTERNAL_SERVER_ERRORinstead ofGRAPHQL_VALIDATION_FAILED) and passes with this change.errorCodes.test.tsruns the real server without a database: unknown field, syntax error, too deep, missing and invalid variable, unknownoperationName, and an unexpected resolver error that is still hidden.eslint backend/src/serverandtsc --noEmitinbackendpass.Not done
docs/API.mdhas formatting differences from Prettier in the environment table (not from this PR); I left them alone to keep the diff small.🤖 Generated with Claude Code