Skip to main content

Error codes

Vluna uses stable machine-readable error codes for programmatic handling and support.

Source of truth

Error code definitions live in:

  • packages/contracts/error-codes.json

How to use error codes

In your integration:

  • Branch on code, not on message.
  • Treat messages as user-facing or operator-facing text only.
  • Log the full envelope and X-Request-Id when present.

The HTTP envelope carries code at the top level. Decision-specific diagnostic fields are in meta. For example, an entitlement failure includes resource_type, feature_code, and feature_family_code so the rejected resource is visible in logs.

SDK error shape

In exception mode, current TypeScript and Python SDK releases preserve the raw response envelope under VlunaAIError.details.body. The exception's code field is reserved but is not populated from the response envelope today, so read the nested body when branching on a server error:

import { VlunaAIError } from '@vlunaai/sdk'

try {
await runGatedOperation()
} catch (error) {
if (error instanceof VlunaAIError) {
const body = error.details?.body as
| { code?: string; meta?: Record<string, unknown> }
| undefined
console.error({
status: error.status,
code: body?.code,
resource: body?.meta,
})
}
}
from vlunaai import VlunaAIError

try:
await run_gated_operation()
except VlunaAIError as error:
body = (error.details or {}).get('body')
envelope = body if isinstance(body, dict) else {}
print({
'status': error.status,
'code': envelope.get('code'),
'resource': envelope.get('meta'),
})

With SDK result mode, inspect the returned result instead of an exception. Python gate_preflight() returns GatePreflightSuccess | GatePreflightError; both expose the actual HTTP status, while the error result also exposes typed ok, code, hints, meta, and trace_id fields.

Entitlement codes

  • ENTITLEMENT.REQUIRED: the resource requires entitlement, but no matching allow entry exists.
  • ENTITLEMENT.DENIED: an explicit deny entry wins entitlement resolution.

Both use HTTP 403, are non-retryable until configuration changes, and return the rejected resource in meta.

Use the code metadata to drive retry decisions where available:

  • never retry validation failures
  • retry transient failures with backoff
  • retry write timeouts via idempotency replays