Overview
When an ION API request fails, two things tell you what went wrong. The HTTP status code gives you a coarse category and theerrors[] payload in the response body gives you the specific message. That message often points directly at the fix.
A typical error response looks like this:
errors[]. Authentication and transport failures are the exception. The auth layer can return a 4xx or 5xx status code before GraphQL runs.
HTTP status reference
One exception to the
400 row: a request whose body is entirely empty returns 200 with the error in errors[], like any other GraphQL error.
401 Unauthorized
ION rejects the request at the authentication layer. Here are the common messages and their fixes:403 Forbidden
The request authenticated successfully, but the principal isn’t authorized for the operation. The distinct causes each have a different fix.Sample 403 payload
UPDATE) and the resource type (Purchase Order) are the two pieces an admin needs to find the missing role permission.
404 Not Found
ION returns a 404, and a GraphQLnull for the field, when the entity doesn’t exist or doesn’t belong to your tenant. The two cases are intentionally indistinguishable to prevent enumeration. A 404 doesn’t leak that an ID exists in another org.
Common causes:
- An ID typo.
- The entity was soft-deleted.
- A cross-tenant ID. See 403 above. Sometimes this surfaces as a 404 instead, depending on the resolver.
parts(filters: { id: { in: [42] } }) { edges { node { id } } } instead of part(id: "42"). The filtered query returns an empty edges array. That confirms a tenant or scope issue.
409 Concurrency conflict
ION uses optimistic concurrency control via the_etag field. Every mutable entity returns an _etag on read. Mutations require you to pass back the _etag you received. If another writer modified the entity in the meantime, the etag won’t match and ION returns a 409.
- Re-read the entity to get the latest
_etagand the latest field values. - Re-apply your changes on top of the new state.
- Retry the mutation with the new
_etag.
422 Validation error
The request was structurally valid and authorized, but a field value violated a domain rule:- A quantity is zero or negative.
- A required field is missing.
- A date is out of range.
- A string exceeds the maximum length.
- An enum value is not allowed.
429 Rate limit
ION applies fair-use rate limiting on the/graphql endpoint. Production traffic patterns rarely hit it. If you do, the response is HTTP 429.
Address it in this order:
- Implement exponential backoff in your client. Start at 1 second, double up to about 30 seconds, and add jitter.
- Batch related queries. One query selecting many fragments beats several queries that each select one fragment.
- Cache locally. For data that doesn’t change often, such as parts and procedures, don’t re-fetch every time.
5xx Server errors
A 5xx response indicates a failure on ION’s side. These responses are safe to retry with exponential backoff.- Retry with exponential backoff. Use 1, 2, 4, and 8 seconds.
- After three consecutive failures across about 30 seconds, surface the error to the user or on-call.
- Check ION’s status page if available, or contact support if the error persists.
GraphQL errors[] shape
Inside the GraphQL response body, an HTTP 200, theerrors array is the source of truth:
A partial
data payload with a non-empty errors[] means the returned fields are valid and one or more other fields failed. Most clients merge these. Yours should too.
Troubleshooting flow
- Check the HTTP status.
- If it’s a 200, parse
errors[]from the response body. - Match the message against the tables on this page.
- If the message is unfamiliar, its wording usually points at the offending field, permission, or resource. Search for it in Authentication and the tables on this page.
- If you’re still stuck, reproduce the call in the API Playground, which surfaces errors more readably. Paste the request and error into a support ticket.
Most 403s are fixed by granting the user’s role the missing permission. Check
permissions before you change code. For a 409, show the conflict to a human so
they can re-merge.