> ## Documentation Index
> Fetch the complete documentation index at: https://plain-docs-orca-916-agent-docs-restructure.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Error handling

> GraphQL queries and mutations require different error handling.

Plain models query errors and mutation errors differently, because the two fail for different reasons:

* **Queries** fail for only three common reasons: unauthenticated, forbidden, or an internal server error. Unauthenticated and forbidden mean the API keys are invalid; internal server errors should be retried.

* **Mutations** return errors regularly as part of the normal business flow, due to invalid inputs. Errors include enough detail to display to whoever is using your product.

## Query errors

Query errors aren't modeled in the GraphQL schema, but rather use [GraphQL's error extensions](https://www.apollographql.com/docs/apollo-server/data/errors/).

If the query returns the value `null`, the entity was not found (equivalent to an HTTP 404 in a REST API).

The list of error extensions that can be returned by queries:

* `GRAPHQL_PARSE_FAILED`: The GraphQL operation string contains a syntax error. The request should not be retried.
* `GRAPHQL_VALIDATION_FAILED`: The GraphQL operation is not valid against the schema. The request should not be retried.
* `BAD_USER_INPUT`: The GraphQL operation includes an invalid value for a field argument. The request should not be retried.
* `UNAUTHENTICATED`: The API key is invalid. The request should not be retried.
* `FORBIDDEN`: The API key is unauthorized to access the entity being queried. The request should not be retried.
* `INTERNAL_SERVER_ERROR`: An internal error occurred. The request should be retried. If this error persists, please get in touch at [help@plain.com](mailto:help@plain.com) and report the issue.

## Mutation errors

All mutations return with an `Output` type that follow a consistent pattern of having two optional fields,
one for the result and one for the error. If the error is returned then the mutation failed.

```tsx theme={null}
type Example {
  data: String!
}

type ExampleOutput {
  # example is the result of the mutation, is only returned if the mutation succeeded
  example: Example
  # if error is returned then the mutation failed
  error: MutationError
}
```

Every `MutationError` has the following fields (assuming you included all these fields in your query):

* **message:** written for a developer, not for whoever is using your product.
* **type:** one of `VALIDATION`, `FORBIDDEN`, `INTERNAL`.
  * Where `VALIDATION` means input validation failed. See the fields for details on why the input was invalid.
  * Where `FORBIDDEN` means the user is not authorized to do this mutation. See `message` for details on which permissions are missing.
  * Where `INTERNAL` means an unknown internal server error occurred. Retry in this scenario and contact [help@plain.com](mailto:help@plain.com) if the error persists.
* **code:** a unique error code for each type of error returned. This code can be used to provide a localized or user-friendly error message. You can find the [list of error codes](/graphql/error-codes) documented.
* **fields:** an array containing all the fields that errored
  * **field:** the name of the input field the error is for.
  * **message:** an English technical description of the error, written for a developer rather than for whoever is using your product.
  * **type:** one of `VALIDATION`, `REQUIRED`, `NOT_FOUND`.
    * Where `VALIDATION` means the field was provided, but didn't pass the requirements of the field. See the `message` on the field for details on why.
    * Where `REQUIRED` means the field is required. String inputs may be trimmed and checked for emptiness.
    * Where `NOT_FOUND` means the input field referenced an entity that wasn't found. For example, you tried to resolve an issue that doesn't exist/was deleted.
