Upside Down Research, LLC · Est. MMXXIII A little different look at the world
Pre-release · subject to change
Documentation

Error Reference

All Tupshar API errors use a consistent JSON envelope and a fixed set of error codes.

Response Envelope

{
  "error": {
    "code": "not_found",
    "message": "Document 01HXYZ not found",
    "request_id": null
  }
}

The error field is an object (not a string) with:

FieldTypeDescription
codestringMachine-readable error code (see table below)
messagestringHuman-readable description
request_idstring | nullOpaque request identifier for support; may be null
detailsobjectPresent on validation_failed — field-level validation errors

Error Code Reference

HTTP StatusCodeWhen you'll see it
400bad_requestInvalid query mode/parameters, unparseable scopes, or unknown filename match mode
401unauthorizedMissing or invalid Authorization header, or revoked/expired key
403forbiddenKey lacks permission for the requested resource
403quota_exceededOver your document count or storage quota
404not_foundDocument ID does not exist, or endpoint URL is wrong
409conflictA document with that filename already exists
412precondition_failedIf-Match header provided but ETag did not match
413payload_too_largeRequest body exceeds 8 MiB, or document contents exceed 4 MiB
415unsupported_media_typeDocument contents contained a NUL byte or a forbidden control character
422validation_failedRequest parsed but failed semantic validation; see details
422unprocessable_entityRequest parsed but cannot be acted on as submitted
428precondition_requiredPUT sent without an If-Match header
429rate_limitedOver 60 requests/min sustained rate
500internalUnexpected server error
501not_implementedEndpoint or feature not yet available

Examples

validation_failed (422)

{
  "error": {
    "code": "validation_failed",
    "message": "Request validation failed",
    "request_id": null,
    "details": {
      "filename": "must not be empty"
    }
  }
}

precondition_required (428)

PUT /v1/file/:id requires an If-Match: <etag> header to prevent lost updates. Sending a PUT without one returns:

{
  "error": {
    "code": "precondition_required",
    "message": "PUT requires an If-Match header with the current ETag",
    "request_id": null
  }
}

quota_exceeded (403)

{
  "error": {
    "code": "quota_exceeded",
    "message": "Storage quota exceeded",
    "request_id": null
  }
}

rate_limited (429)

Rate-limit responses include a Retry-After header (seconds to wait). There are no X-RateLimit-* headers.

HTTP/1.1 429 Too Many Requests
Retry-After: 14
{
  "error": {
    "code": "rate_limited",
    "message": "Rate limit exceeded",
    "request_id": null
  }
}

Retry Guidance

CodeRetryable?Guidance
bad_requestNoFix the request
unauthorizedNoCheck/rotate API key
forbiddenNoCheck permissions or quota
quota_exceededNoFree up quota first
not_foundNoDocument does not exist
conflictNoDocument already exists; use PUT to update
precondition_failedConditionalRe-fetch the ETag, then retry
precondition_requiredConditionalAdd If-Match header and retry
payload_too_largeNoReduce request/document size
unsupported_media_typeNoAdd Content-Type: application/json
validation_failedNoFix the failing fields
unprocessable_entityNoReview request semantics
rate_limitedYesWait for Retry-After seconds, then retry
internalYesRetry with exponential backoff
not_implementedNoFeature not available

For quota limits and rate limit details see @/docs/reference/quotas.md.