Errors
With the exception of authentication failures, errors arrive as HTTP 200 with the
failing field set to null and an entry in errors:
{"errors":[{"path":["tasks","createTask"],
"extensions":{"errorType":"PERMISSION_DENIED",
"errorMessage":"Permission required: canManageTasks"}}]}
Client code that only checks the status code will read this as success. Inspect
errors on every response.
errorType
| Value | Meaning | Retry? |
|---|---|---|
AUTHENTICATION_ERROR | No credentials, or credentials that are not sufficient for this surface | No — fix the key |
PERMISSION_DENIED | The key is valid but lacks the required permission flag | No — the key will never grow the flag on its own |
CONDITION_ERROR | Bad input or bad state: a missing entity, an illegal transition, a validation failure | No — fix the input |
EFFECT_ERROR | A server-side failure while performing the operation | Yes, with backoff |
VALIDATION_ERROR / PARSING_ERROR | The query text itself is wrong — unknown field, bad argument type, syntax error | No — fix the query |
errorMessage is written to be shown to a person. Surface it rather than replacing it
with your own generic text; it usually names the exact permission, field or entity at
fault.
HTTP 401
A missing, malformed, expired or revoked key returns HTTP 401 with no GraphQL body worth parsing. The response is deliberately uniform across those cases — it will not tell you which one you hit. See Authentication.