RFC: Add Schema Coordinate to GraphQL Errors
Add an optional coordinate field to GraphQL errors that contains the schema coordinate of the object field or field argument associated with the error, enabling direct identification of schema elements that caused runtime errors.
📜 Problem Statement
When a GraphQL error occurs, developers must perform multiple steps to identify which type system member caused the error:
- Parse the schema
- Parse the operation
- Traverse the operation based on the
pathfield in the error
This process is cumbersome and requires tooling to correlate runtime errors back to their schema definitions. While the path field identifies where in the response the error occurred, it doesn't directly indicate which schema element is responsible for the error.
Example
Consider this error response:
{
"errors": [
{
"message": "Name for character with ID 1002 could not be fetched.",
"locations": [{ "line": 6, "column": 7 }],
"path": ["hero", "heroFriends", 1, "name"]
}
]
}
To determine that this error originated from the Human.name field in the schema, developers must:
- Load and parse the schema
- Parse the GraphQL operation
- Walk through the operation following the path
["hero", "heroFriends", 1, "name"] - Determine the types at each step to identify that
heroFriendsreturns[Friend] - Conclude that the error is associated with
Human.name
💡 Proposed Solution
Add an optional coordinate field to GraphQL errors that directly references the object fiel or field argument where the error originated.
Example
{
"errors": [
{
"message": "Name for character with ID 1002 could not be fetched.",
"locations": [{ "line": 6, "column": 7 }],
"path": ["hero", "heroFriends", 1, "name"],
"coordinate": "Human.name"
}
]
}
In this example coordinate directly identifies Human.name in the schema as the source, without requiring any parsing or traversal
-
Simplified Error Tracking: Developers can immediately identify which schema element caused an error without complex analysis.
-
Better Tooling Support: IDEs, monitoring systems, and debugging tools can directly link errors to schema definitions.
The coordinate field should be included when:
- An error originates from resolving a specific object field -> object field coordinate
- An error originates from resolving a specific field argument -> field argument coordinate
- An error originates from coercing a value of a input object -> field argument of the field that the input object is passed to
The coordinate field may be omitted when:
- The error is not associated with a specific schema element
- The server implementation cannot determine the appropriate coordinate
Deploy Preview for graphql-spec-draft ready!
| Name | Link |
|---|---|
| Latest commit | 04e2431a3efc18e3b50b5d0e158631ba7fe6c0b5 |
| Latest deploy log | https://app.netlify.com/projects/graphql-spec-draft/deploys/6900a65b5fcd5b0008dafddb |
| Deploy Preview | https://deploy-preview-1200--graphql-spec-draft.netlify.app |
| Preview on mobile | Toggle QR Code...Use your smartphone camera to open QR code link. |
To edit notification comments on pull requests, go to your Netlify project configuration.
This would really help us simplify error tracking!
Adding the schema coordinate together with the existing path expose the schema information. Now the user knows that hero's heroFriends is [Human], and it has name in it. An attacker can predict a lot of information about the schema unsafely by using required argument errors etc too.
If you say most clients request __typename anyway, but this is a request which is evaluated by the server, and the resolution of __typename is not the same with exposing the schema coordinate in every error.
If we already have __typename + path, we can always find the schema coordinate anyways. So why would we need an extra schema coordinate property in the errors?
After trying to actually implement walking the path to determine schema coordinate, it appears that the coordinate can be impossible to determine with certitude.
If there is a Union or an Interface involved in the path, you will need to visit the result to know the actual type.
But, in combination with non-nullable field, you have situations where can't determine the actual coordinate.
Example:
#schema.gql
interface Node {
id: String!,
}
type Query {
node(id: String!): Node!
}
type User implements Node {
id: String!,
}
type Comment implements Node {
id: String!,
}
#query.gql
query {
node(id: 'a-user-id') {
id
__typename
}
}
If an error occurs in the id resolver, you will get this result:
{
data: null,
errors: [{
message: 'An error occured',
path: ['node', 'id']
}]
}
Now you have no way to determine if the coordinate is actually User.id or Comment.id.
The same applies for Unions.
@EmrysMyrddin You're right but the security concern is still there, and if this schema coordinate property will be standard in the error object, then we should document this concern clearly.
in combination with non-nullable field, you have situations where can't determine the actual coordinate.
@EmrysMyrddin this is yet another use case for onError: NULL and disabling error propagation. At this point error propagation has a bunch of issues (see also https://github.com/graphql/nullability-wg/) so I would rather optimise for the new onError: NULL case.
@martinbonnin not sure to entirely understand what you mean with this. From what I understand, you have multiple choices for the execution behavior on error. So I think that whatever the choice you made, you should always be able to know the schema coordinate where the error happened, just as you always now the path at which an error happened.
I hear the security concern, and we should make it obvious the implication of this, just as it has to be obvious the implications of allowing introspection on your schema. We can also recommend to library and server maintainers to mask this by default on production environment, just as unhandled exceptions should be masked by default.
whatever the choice you made [for onError], you should always be able to know the schema coordinate where the error happened
@EmrysMyrddin Not sure I agree. I don't want us to keep adding to the spec for mistakes that were made 10 years ago ( and were OK at that time but things have changed, this is a long story).
If you keep using onError: PROPAGATE in 2026 then you can't find the error coordinate for some errors. It's too bad but there is a solution: use onError: NULL and a smart client.
onError: NULL solves this specific issue together with a bunch of other ones (semantic nullability, etc...) all at once 🥳 All of that without adding to the language. It's a win for everyone!
I do have my reservations the longer i think about this proposal. I do think it's necessary to have this coordinate as a error for telemetry, but I question the value for the client of it. I would really want to encourage the implementations to map each error to a specific coordinate, hence the proposal, but i am not sure if we need to add it to the response.. What's the value for the client to know that the error happened at Query.foo? How do we approach this?
This may just be a feature of graphql/otel-wg
In my opinion, coordinate has value on its own, not just for Telemetry, but also for developers to debug an error.
I hear that with this new error propagation mode you can programatically find out the resolver by walking the path. But that's a non-trivial algorithm that you will have to run for each error before being able to report them. While it's straight forward to add it at error construction time, because information is at hand.
And this is only true for programatic usage. If you are a developer, looking at GraphQLError in logs of your application or server, you probably don't have access to the corresponding result data or even just the query document. So you would not be able to disambiguate an error path. Even just finding out the resolver can be tricky if the document contains label.