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 §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 §13. The ones an
application meets in normal work:
cannotCalculateChanges: read again (Keeping up §3).forbidden: the credential, or a delegation, lacks the right the method needs; the description names it. Withdrawn lines show up this way.stateMismatch: anifInStatethat 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 (§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
429withRetry-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):
429with{ "error": "rate_limited" }and noRetry-After. Registration has its own limits (Registration §5). The device grant's poll answersslow_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 and Registration. 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.