Skip to main content

Errors

Handle the AstraBox error envelope and decide whether a failed request can be retried.

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": "cannot delete session while the agent is working",
"data": { "runtime_status": "working" },
"error": {
"code": "SESSION_BUSY",
"status_code": 409,
"category": "state",
"retryable": true,
"owner": "session",
"user_message": "cannot delete session while the agent is working"
}
}

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, store, 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
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/runtime-profiles" \
-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 RuntimeProfile 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
  • The Agent is working while a request deletes or archives the Session, ends the conversation, or terminates its sandbox
  • Agent or RuntimeProfile state does not allow the requested operation
{
"code": "SESSION_BUSY",
"message": "cannot delete session while the agent is working",
"data": { "runtime_status": "working" },
"error": {
"code": "SESSION_BUSY",
"status_code": 409,
"category": "state",
"retryable": true,
"owner": "session",
"user_message": "cannot delete session while the agent is working"
}
}

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": "the record store is unavailable, please retry",
"data": null,
"error": {
"code": "PERSISTENCE_UNAVAILABLE",
"status_code": 503,
"category": "persistence",
"retryable": true,
"owner": "store",
"user_message": "the record store is 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.