Skip to main content

Errors

Prism is a GraphQL API, so errors arrive two ways: HTTP status codes for transport- and auth-level problems, and a GraphQL errors array (inside an otherwise-200 response) for problems with the query itself.

HTTP errors

StatusMeaningCause / fix
401 UnauthorizedInvalid or missing tokenSend a valid Authorization: Bearer <token>. Get one from the Tokens endpoint; see Authentication.
403 ForbiddenToken is valid but lacks the required scopesConfirm the token is for the right account; contact your advocate if it persists.

The token endpoint (POST /v1/users/token) can also return 415 Unsupported Media Type (the Content-Type isn't application/x-www-form-urlencoded) and 422 Unprocessable Entity (a required field is missing).

GraphQL errors

A request that authenticates but has a problem with the query returns 200 OK with an errors array, per the GraphQL spec — so check errors even on a 200 response:

{
"errors": [
{ "message": "Cannot query field \"foo\" on type \"Offer\"." }
],
"data": null
}

Common causes: requesting a field that doesn't exist, omitting a required argument (such as player_id), or a malformed query. GraphQL is introspective, so you can confirm valid queries and fields from any GraphQL client.

Validation errors

Arguments that are the right type but the wrong value fail validation. Unlike the query errors above, these are field errors: they are raised while the field is being resolved, so the field resolves to null and data stays an object.

{
"errors": [
{
"message": "Validation failed for the field [offers].",
"path": ["offers"],
"extensions": {
"validation": {
"player_id": [
"The player id field must not be greater than 255 characters."
]
}
}
}
],
"data": { "offers": null }
}
Do not branch on data === null

data is null only for the pre-execution query errors in the section above. A validation failure returns 200 OK with data present and the failing field set to null, so code that treats data === null as "the request failed" will miss every validation error.

Check for a non-empty errors array instead, and use each error's path to identify which field failed.

One error per field, not per argument

All of a single field's invalid arguments collapse into one error, with every reason in that error's validation map:

{ offers(player_id: "abc", limit: 0, language: "toolong", sort: "bogus.sideways") { id } }

returns one error whose validation holds sort, limit, and language together. Querying two fields that both fail returns two errors, one per field, each with its own path — so iterate errors[] rather than reading errors[0], and read extensions.validation rather than matching on message.

Rules by argument

ArgumentRuleError
player_idRequired, non-empty, 255 characters or fewerThe player id field must not be greater than 255 characters.
sortMust be dot separated: one of epc.asc, epc.desc, last_activation.asc, last_activation.descNot dot separated: The selected sort is invalid, it must be a dot separated string specifying sort option and direction. Unknown option: ...the provided sort option (bogus) is invalid. Unknown direction: ...the provided direction (sideways) is invalid.
limitInteger, 1 or greaterThe limit field must be at least 1.
language2 to 5 charactersThe language field must not be greater than 5 characters.

The rules above apply to offers. links takes only player_id, so the first row is the whole of its validation.

playerOffers

playerOffers applies the same player_id and language rules. Its limit is capped rather than open-ended, and it adds after:

ArgumentRuleError
limitInteger, 1 to 100. Defaults to 50 when omittedThe limit field must not be greater than 100.
afterOptional. Must be a next_cursor value from an earlier playerOffers responseSee Invalid pagination cursor

Invalid pagination cursor

playerOffers paginates with an opaque cursor. Passing an after value the query did not issue is reported as an error rather than quietly restarting at the first page, because a silent reset is indistinguishable to the caller from a list that never ends.

Unlike the validation failures above, this arrives without an extensions.validation map. The caller-facing explanation is in extensions.reason:

{
"errors": [
{
"message": "An error occurred while fetching player offers",
"path": ["playerOffers"],
"extensions": {
"reason": "The `after` cursor is not one this query issued. Omit it to start from the first page."
}
}
],
"data": { "playerOffers": null }
}

Cursors are opaque and only meaningful to the query that issued them. Read next_cursor from the previous response and pass it back unchanged, rather than building or editing one yourself.

Prism validates argument types and lengths only. It does not enforce the player ID character or casing conventions — see Player ID for those, and why they still matter.