GraphQL Errors
In the previous lesson we saw that a response can carry an errors array. Now we open that array up. Every entry in it is a structured object with a fixed set of keys, and learning to read those keys turns a vague “something broke” into a precise “this field, at this position in your query, failed for this reason.”
Anatomy of an error entry
Section titled “Anatomy of an error entry”Each element of errors has one required key and several optional ones the specification defines:
message— a human-readable string describing what went wrong. This is the only mandatory key.locations— a list of{ line, column }positions pointing at the exact place in the query text that triggered the error.path— a list of field names and list indices tracing from the root of the response down to the field that failed, for example["currentTrack", "title"].extensions— a map for machine-readable detail; we devote the whole next-but-one lesson to it.
message is for humans; locations and path are for tools and clients that need to react programmatically. Together they let a client highlight the offending part of the query and route the failure to the right place in its UI.
Two families of error
Section titled “Two families of error”Not all errors arrive at the same stage. The specification distinguishes two families, and the distinction matters because it decides whether you get any data back at all.
flowchart TD Query["Incoming query"] Parse["Parse + validate"] Exec["Execute resolvers"] ReqErr["Request error: errors only, NO data key"] FieldErr["Field error: data present (field null) + errors"] OK["Success: data only"] Query --> Parse Parse -->|"fails"| ReqErr Parse -->|"passes"| Exec Exec -->|"resolver throws"| FieldErr Exec -->|"all resolve"| OK
Request errors happen before execution begins. The query failed to parse, or it parsed but did not validate against the schema — an unknown field, a wrong argument type, a malformed selection. Because execution never started, the response has no data key at all (not even null); it carries only errors.
Field errors (also called execution errors) happen during execution, when a resolver throws or returns an invalid value. By the time one of these fires, the server is already building data, so the response includes data with the failed field nulled out, alongside an errors entry for it. This is the partial-success case we will study in depth next lesson.
Watching a request error vs a field error
Section titled “Watching a request error vs a field error”The runner below runs two operations against the same schema. The first asks for a field that does not exist — a validation failure, so it is a request error with no data. The second runs a valid query whose resolver throws — a field error, so data comes back with the failed field as null. Compare the two outputs.
Look at the first block: there is no data key, only errors, and the entry carries locations pointing at where ghostField appeared in the query. Now the second block: data is present with nowPlaying set to null, and the matching error carries a path of ["nowPlaying"] so a client knows exactly which field went missing. Same errors array, two very different situations — and you can tell them apart by whether data exists.