Error codes
Explicit HTTP JSON errors (RFC 7807)
Ordinary Ujex HTTP handlers that return JSON errors use RFC 7807 Problem Details with
Content-Type: application/problem+json. The stable members are type, title, status,
and detail; instance identifies the request path when available. Bernato runtime handlers
also retain their previous error string as an extension so existing clients can migrate
without losing their old discriminator.
{
"type": "https://docs.ujex.dev/reference/error-codes#invalid-query",
"title": "Invalid query",
"status": 400,
"detail": "cursor is malformed",
"instance": "/auditAnchorsPublic"
}
invalid-request
The HTTP body is malformed or does not match the endpoint contract. Fix it before retrying.
authentication-failed
An HMAC signature or signing-key lookup failed. Refresh the configured credential; never retry an unchanged invalid signature indefinitely.
invalid-query
A query parameter is malformed. The public audit-anchor feed uses this for invalid limit or
cursor values.
method-not-allowed
The route does not support the HTTP method. Use the method named by the Allow response header.
internal-error
The handler could not complete a read. The response is deliberately generic and does not expose provider or storage details.
The unauthenticated auditAnchorsPublic feed is ordered by unique anchor seq descending. Its
existing project, schema, and anchors fields remain; pagination adds limit, has_more, and
cursor. Request the next page with the returned cursor. A null cursor and has_more: false mean
the scan is complete. Limits are clamped to 1–200 and the default is 50.
Protocol-specific exceptions are intentional: OAuth endpoints retain the error bodies required by RFC 6749, RFC 7009, and RFC 7662. Signed Postbox provider webhooks retain their existing plain-text transport acknowledgement/error bodies because provider retry behavior depends on that contract.
Firebase callable errors
Ujex Firebase callables return HttpsError. In JavaScript, codes are prefixed with
functions/; raw callable responses use the matching Google RPC status.
| Callable code | HTTP | Meaning | Recovery |
|---|---|---|---|
invalid-argument | 400 | Missing, malformed, unsupported, or out-of-range input. | Fix the request; do not retry unchanged. |
failed-precondition | 400 | Current server state cannot perform the operation. | Read the message/details and resolve the named state first. |
unauthenticated | 401 | Missing, expired, or invalid human/agent authentication. | Refresh sign-in or exchange the agent credential again. |
permission-denied | 403 | Caller is authenticated but lacks ownership, role, scope, mandate, or policy permission. | Narrow/change authority; never treat as allow. |
not-found | 404 | The resource does not exist or is not visible to this caller. | Verify the ID and tenant; do not create a substitute implicitly. |
already-exists | 409 | A unique claim or active record already exists. | Load/use the existing state or choose another unique value. |
aborted | 409 | Optimistic version or transaction state changed. | Reload current state, recompute the request, then retry. |
resource-exhausted | 429 | Rate, quota, or budget gate rejected work. | Back off or obtain a valid budget/quota change. |
unavailable | 503 | A provider/control dependency is temporarily unavailable or outcome is uncertain. | Retry with bounded exponential backoff and the same idempotency key. |
deadline-exceeded | 504 | Work did not finish before its deadline. | Treat the outcome as uncertain; reconcile before repeating a mutation. |
internal | 500 | Server invariant or unhandled provider failure. | Record function/request context and report it; do not assume the action failed safely. |
Example in JavaScript
try {
await invokeTool({name: 'crm.update', args, sessionId});
} catch (error) {
const code = (error as {code?: string}).code;
if (code === 'functions/aborted') {
// Reload the current version before retrying.
} else if (code === 'functions/unavailable') {
// Back off and reuse the same operation/idempotency identity.
} else {
// Stop. In particular, never reinterpret a permission/policy error as allow.
throw error;
}
}
Domain details
Many failures include structured details—for example budget state, mailbox state, policy
reason, or tool HTTP status. Treat details as diagnostic data, not a stable authorization
signal unless the endpoint documents the field. The code remains the recovery category.
Firebase callable errors are not RFC 7807 problem+json; clients must continue to use the
callable code and structured details contract above.