Skip to main content

Errors

The AstraBox API returns errors in a consistent envelope. Each error response carries structured fields suitable for programmatic handling and debugging.

Error envelope

AstraBox REST resource handlers use this JSON structure:

{
"code": "SESSION_BUSY",
"message": "session is busy",
"data": null,
"error": {
"code": "SESSION_BUSY",
"status_code": 409,
"category": "state",
"retryable": true,
"owner": "session",
"user_message": "session is busy"
}
}

Every response also carries a W3C traceparent header. Unexpected server errors include the same trace ID in data.trace_id so an operator can correlate the response with logs.

Field descriptions

FieldTypeRequiredDescription
codestringYesStable error code for programmatic handling
messagestringYesMessage safe to show to the caller
dataany | nullYesError-specific structured data, when available
error.codestringYesSame stable error code as the top-level code
error.status_codeintegerYesStatus registered for the error code; use the actual HTTP response status for transport handling
error.categorystringYesError category, such as request, auth, state, or persistence
error.retryablebooleanYesWhether retrying after a delay can succeed without changing the request
error.ownerstringYesComponent or party that must act: client, session, mongo, runtime, template, platform, or unknown
error.user_messagestringYesMessage safe to show to the caller
error.debug_messagestringNoAdditional diagnostic message when the error provides one
error.evidenceobjectNoStructured evidence for diagnosis
error.cause_codestringNoLower-level cause code when one is available

Error types

Error codes describe the specific failure; HTTP status describes how the request completed. Common status groups are:

HTTP statusExample codeDescription
400 or 422INVALID_REQUESTInvalid or missing request parameters
401AUTH_REQUIRED, UNAUTHORIZED, TOKEN_EXPIREDAuthentication failed or is required
403FORBIDDEN, API_TOKEN_SCOPE_INSUFFICIENTAuthenticated but not authorized for the operation
404NOT_FOUND, SESSION_NOT_FOUNDTarget resource is missing or inaccessible
409SESSION_BUSY, IDEMPOTENCY_KEY_CONFLICTResource state conflicts with the operation
429ADMISSION_DENIEDDeployment admission policy refused the work
499REQUEST_CANCELLEDThe caller cancelled the request
5xxPERSISTENCE_UNAVAILABLE, UNEXPECTED_SERVER_ERRORAstraBox, infrastructure, or an upstream dependency failed

The table contains examples, not a complete error-code catalog. Use the deployed release's /openapi.json and the fields returned by the failing route.

Error type details

400 or 422 — INVALID_REQUEST

The request format or parameters are invalid.

Common triggers:

  • Missing required field (for example, permission_mode)
  • Field type mismatch (such as a number where a string is expected)
  • Parameter outside the accepted range
  • Malformed JSON
{
"code": "INVALID_REQUEST",
"message": "permission_mode is required",
"data": null,
"error": {
"code": "INVALID_REQUEST",
"status_code": 400,
"category": "request",
"retryable": false,
"owner": "client",
"user_message": "permission_mode is required"
}
}
# Example trigger: missing the permission_mode field
curl --fail-with-body --silent --show-error \
-X POST "$SERVICE_URL/api/v1/sessions/$SESSION_ID/permission-mode" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'

401 — authentication errors

Authentication failed.

Common triggers:

  • Missing credential on a protected route
  • Malformed or invalid bearer token
  • Expired or revoked Access Token
  • Credential issued by an untrusted issuer
{
"code": "TOKEN_EXPIRED",
"message": "bearer token expired; obtain a new one from your token issuer",
"data": null,
"error": {
"code": "TOKEN_EXPIRED",
"status_code": 401,
"category": "auth",
"retryable": false,
"owner": "client",
"user_message": "bearer token expired; obtain a new one from your token issuer"
}
}
# Example trigger: invalid token
curl --fail-with-body --silent --show-error \
"$SERVICE_URL/api/v1/agents" \
-H "Authorization: Bearer invalid-token"

403 — authorization errors

The caller is authenticated but not authorized.

Common triggers:

  • The identity cannot manage the target Agent
  • The Access Token does not include the scope required for the operation
  • A non-administrator calls an administration route
{
"code": "API_TOKEN_SCOPE_INSUFFICIENT",
"message": "API token requires scope astrabox:admin",
"data": { "required_scope": "astrabox:admin" },
"error": {
"code": "API_TOKEN_SCOPE_INSUFFICIENT",
"status_code": 403,
"category": "auth",
"retryable": false,
"owner": "client",
"user_message": "API token requires scope astrabox:admin"
}
}
# Example trigger: a read-only token calls an administration API
curl --fail-with-body --silent --show-error \
"$SERVICE_URL/api/v1/admin/environments" \
-H "Authorization: Bearer $READ_TOKEN"

404 — not-found errors

The target resource does not exist or is not visible to the caller.

Common triggers:

  • Agent, Session, or Environment ID does not exist
  • The resource was deleted
  • The caller is not authorized to discover another owner's resource
  • URL path typo
{
"code": "SESSION_NOT_FOUND",
"message": "session not found",
"data": null,
"error": {
"code": "SESSION_NOT_FOUND",
"status_code": 404,
"category": "request",
"retryable": false,
"owner": "session",
"user_message": "session not found"
}
}
# Example trigger: nonexistent Session
curl --fail-with-body --silent --show-error \
"$SERVICE_URL/api/v1/sessions/session_nonexistent_123" \
-H "Authorization: Bearer $ACCESS_TOKEN"

409 — conflict errors

Resource state conflict prevents the operation.

Common triggers:

  • Same idempotency key reused for a different conversation
  • Session is already processing another turn
  • Agent or Environment state does not allow the requested operation
{
"code": "SESSION_BUSY",
"message": "session is busy",
"data": null,
"error": {
"code": "SESSION_BUSY",
"status_code": 409,
"category": "state",
"retryable": true,
"owner": "session",
"user_message": "session is busy"
}
}

5xx — server and dependency errors

AstraBox, its infrastructure, or an upstream dependency failed.

Common triggers:

  • Database unavailable
  • Sandbox or Agent program failed to start
  • Identity provider or model gateway unavailable
  • Unexpected internal failure
{
"code": "PERSISTENCE_UNAVAILABLE",
"message": "mongodb timeout/unavailable, please retry",
"data": null,
"error": {
"code": "PERSISTENCE_UNAVAILABLE",
"status_code": 503,
"category": "persistence",
"retryable": true,
"owner": "mongo",
"user_message": "mongodb timeout/unavailable, please retry"
}
}

Retry when error.retryable is true, or when a 429 response provides data.retry_after_seconds. Use bounded exponential backoff and wait at least the provided number of seconds.

Error handling best practices

  1. Branch on code and error.retryable, not only on the HTTP status.
  2. Log the traceparent response header, code, and message for diagnostics.
  3. Inspect data, error.evidence, and error.cause_code when present.
  4. Do not retry when error.retryable is false unless a 429 response provides data.retry_after_seconds.
  5. Use bounded exponential backoff for retryable responses.
# Request with error handling
headers=$(mktemp)
trap 'rm -f "$headers"' EXIT
response=$(curl --silent --show-error -D "$headers" -w "\n%{http_code}" \
"$SERVICE_URL/api/v1/agents" \
-H "Authorization: Bearer $ACCESS_TOKEN")

http_code=$(echo "$response" | tail -1)
body=$(echo "$response" | sed '$d')

if [ "$http_code" -ge 400 ]; then
error_code=$(echo "$body" | python3 -c "import sys,json; print(json.load(sys.stdin)['code'])")
retryable=$(echo "$body" | python3 -c "import sys,json; print(json.load(sys.stdin)['error']['retryable'])")
traceparent=$(sed -n 's/^[Tt]raceparent: //p' "$headers" | tr -d '\r')
echo "API error: $error_code retryable=$retryable traceparent=$traceparent"
fi

Next steps

  • Overview — how AstraBox fits together.