# Errors and rate limits Errors come at four levels: the HTTP answer, a method of a request, an object of a `/set`, and the sign-in endpoints. ## 1. HTTP | Status | When | Do | |---|---|---| | `401` | no credential, or one no longer valid (expired, revoked, the consent withdrawn whole) | refresh the access token once; if that fails, sign in again. The `WWW-Authenticate` header names `resource_metadata` ([Discovery](discovery.md) §2) and, for a bad token, `error="invalid_token"` | | `403` | the credential is valid but holds no data scope the API serves (`WWW-Authenticate: Bearer …, error="insufficient_scope", scope="drive:read"`) | sign in with the scopes the application needs | | `404` | a download of a blob that does not exist or this credential may not read | — | | `400` | not a JMAP request, or one over a limit: an RFC 7807 problem whose `type` is `urn:ietf:params:jmap:error:notJSON`, `notRequest`, `limit` (with `limit` naming it, such as `maxCallsInRequest`) or `unknownCapability` (RFC 8620 §3.6.1) | fix the request | | `429` | a rate limit (§4) | wait `Retry-After` | | `503` | a service of the install is not reachable now (`Retry-After: 5`) | wait and retry | A request that is answered `200` may still hold failed methods (§2). ## 2. Method errors `["error", { "type", "description" }, callId]` in place of the method's answer; the other calls of the request still run. The types this API answers are listed in the [Reference](reference.md) §13. The ones an application meets in normal work: - `cannotCalculateChanges`: read again ([Keeping up](keeping-up.md) §3). - `forbidden`: the credential, or a delegation, lacks the right the method needs; the description names it. Withdrawn lines show up this way. - `stateMismatch`: an `ifInState` that is no longer current; read, then write again. - `requestTooLarge`: more objects than the method takes in one call. ## 3. SetErrors A `/set` writes every object it can and answers a SetError `{ type, description, properties? }` for each one it refused, in `notCreated`, `notUpdated` or `notDestroyed`. The types of each method are in the [Reference](reference.md) (§4.4 for annotations); across the API: | `type` | Meaning | |---|---| | `notFound` | no such object, or not one the credential may read | | `invalidProperties` | a property out of its rules; `properties` names it (`fields/total`, `faces`, `blobId`) | | `contentChanged` | the file's content is not the one the write was made from | | `tooLarge` | an annotation's text over 1 MiB | | `forbidden` | not this credential's to change (another source's object, an embedding without `drive:faces`) | | `overQuota` | an application's own limit: 50 views or 200 pending suggestions per source. Never the person's storage: what an application writes does not count against it | | `dismissed`, `accepted` | the person decided this album suggestion; its key is never offered again | | `removed` | the person removed this view; its key is refused | | `serverFail` | the write did not land; try again later | ## 4. Rate limits Every request an application makes is one of the person's, under the person's limits; the application is told by `429`, never by a quota error. - **JMAP** answers `429` with `Retry-After` (seconds) for too many requests at once (`maxConcurrentRequests`), too many EventSource streams, and an upload past the person's allowance of bytes per hour (small uploads never count). The body is an RFC 7807 problem naming the limit. - **Sign-in endpoints** limit requests that are not signed in by network address (IPv4 address or IPv6 /64): `429` with `{ "error": "rate_limited" }` and no `Retry-After`. Registration has its own limits ([Registration](registration.md) §5). The device grant's poll answers `slow_down`. - Without a `Retry-After`, back off exponentially from 1 second, up to a minute. ## 5. Sign-in errors The token, registration and revocation endpoints answer OAuth errors as JSON `{ "error", "error_description" }` (RFC 6749 §5.2, RFC 7591 §3.2.2): see [Signing in](signing-in.md) and [Registration](registration.md). A few answers of the device and registration endpoints come from the install's general error handler as `{ "error", "message" }`, or as an HTML page unless the request sends `Accept: application/json`: send it on every request to the authorization server.