Skip to content

Errors

API errors use a consistent JSON envelope and standard HTTP status codes.

Error envelope

Application errors return an error object with a machine-readable code and a human-readable message:

json
{
  "error": {
    "code": "NotFound",
    "message": "Bucket not found"
  }
}

Two envelope shapes

Application/handler errors use the { "error": { "code", "message" } } shape above. Infrastructure-level responses from the HTTP layer — notably the rate limiter — use Fastify's { "statusCode", "error", "message" } shape instead. See Rate Limits.

Status codes

StatusCode(s)Meaning
400BadRequest, InvalidArgument, ValidationError, InvalidBucketNameMalformed request, invalid argument, or failed validation
401UnauthorizedMissing or invalid credentials
403ForbiddenAuthenticated, but lacking the required scope or org membership
404NotFoundResource does not exist (or isn't visible to your org)
409ConflictState conflict — duplicate bucket/category name, or a downgrade blocked by current usage
429Rate limit exceeded (see Rate Limits)
500InternalErrorUnhandled server error

Validation errors

Request-body validation failures return 400 with a details array pinpointing each offending field:

json
{
  "error": {
    "code": "ValidationError",
    "message": "Request validation failed",
    "details": [
      { "path": "expiresIn", "message": "Number must be greater than or equal to 60" },
      { "path": "tags.0", "message": "Expected string, received number" }
    ]
  }
}

path is a dot-joined path into your request body (array indices included), so tags.0 refers to the first element of the tags array.

Authorization errors

  • 401 Unauthorized — no credential, or a credential that failed verification. Check the Authorization header (see Authentication).
  • 403 Forbidden — the credential is valid but lacks the needed scope, is restricted to a different bucket, or the user isn't a member of the requested organization. The message names the missing scope, e.g. Missing required scope: write.

Server errors never leak internals

500 InternalError responses carry only a generic message. Stack traces and internal details are logged server-side and never returned to clients.

Released under the AGPL-3.0 License.