API Errors

BitVault uses a stable, machine-readable error taxonomy defined in pkg/apperr. Error codes are versioned with the API — a code that ships in v1 will never be silently repurposed.

Error Response Shape

Every error response is a JSON object with three fields:

{
  "code": "NOT_FOUND",
  "message": "file node abc123 does not exist",
  "request_id": "01J2K4M6N8P0Q2R4S6T8V0W2X4"
}
Field Type Description
code string Machine-readable error code from pkg/apperr
message string Human-readable description; may include safe context details
request_id string Unique ID for this request; maps to the distributed trace

The message field is informational and may change between releases. Build integrations against code, not message.

HTTP Status Mapping

HTTP Status Semantics Example code values
400 Bad Request Validation failure or malformed input INVALID_ARGUMENT, MISSING_REQUIRED_FIELD
401 Unauthorized Not authenticated; token missing, expired, or invalid UNAUTHENTICATED, TOKEN_EXPIRED
403 Forbidden Authenticated but not authorized for this resource PERMISSION_DENIED, INSUFFICIENT_SCOPE
404 Not Found Resource does not exist (or hidden for authz) NOT_FOUND
409 Conflict Resource already exists or state conflict ALREADY_EXISTS, VERSION_CONFLICT
413 Payload Too Large Quota exceeded or file too large for tier QUOTA_EXCEEDED, FILE_TOO_LARGE
429 Too Many Requests Rate limit exceeded RATE_LIMITED
500 Internal Server Error Unexpected server error; investigate via request_id INTERNAL
503 Service Unavailable Dependency unavailable; safe to retry with backoff UNAVAILABLE

Example Error Responses

404 Not Found:

{
  "code": "NOT_FOUND",
  "message": "node 01J2K4M6N8P0Q2R4 does not exist or you do not have access",
  "request_id": "01J2K4M6N8P0Q2R4S6T8V0W2X4"
}

409 Version Conflict (sync push with stale base):

{
  "code": "VERSION_CONFLICT",
  "message": "base version 7 is not current (current: 9); a conflicted copy has been created",
  "request_id": "01J2K4M6N8P0Q2R4S6T8V0W2X5"
}

429 Rate Limited:

{
  "code": "RATE_LIMITED",
  "message": "token rate limit exceeded; retry after 2026-06-12T14:30:00Z",
  "request_id": "01J2K4M6N8P0Q2R4S6T8V0W2X6"
}

Retrying Errors

Code Retry? Strategy
INTERNAL Maybe Retry once with backoff; if persists, report request_id
UNAVAILABLE Yes Exponential backoff with jitter
RATE_LIMITED Yes Wait until Retry-After header value
UNAUTHENTICATED Refresh token first Obtain new access token, then retry
INVALID_ARGUMENT No Fix the request
PERMISSION_DENIED No User lacks the required permission
VERSION_CONFLICT Depends For sync: handle the conflicted copy; for others: re-fetch and retry

:::tip request_id Include the request_id from any error response when filing a support request or bug report. It maps directly to the distributed trace for that request in Jaeger/Tempo, allowing the exact execution path to be inspected end-to-end. :::