> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting: Orby operator errors

> Decode the Orby operator-assistant error codes — ORBY_SESSION_* token failures, ORBY_TOOL_* authorization gates, ORBY_RATE_LIMITED / ORBY_ITERATION_LIMIT / ORBY_TURN_FAILED / ORBY_LLM_FAILED turn failures, ORBY_KB_* knowledge readiness, and ORBY_THREAD_NOT_OWNED — map each to its cause, fix the gate, and decide between retry and escalation.

# Troubleshooting: Orby operator errors

A turn in the [Orby](/concepts/orby-operator-assistant) panel returns an error
envelope, the SSE stream ends in an `error` event, or a knowledge-base search
comes back empty with an outage hint. Every one of those surfaces carries a
stable `ORBY_*` code. This page maps each code to its cause and its fix. The
full platform code list lives in the [error reference](/reference/error-codes);
this page gives you the runbook for the Orby codes.

A typical envelope looks like this — key on `error.code`, never on the
`message` text. On a turn the same fields arrive as the terminal `error` SSE
event, with `code` and `message` inside the `data` payload:

```json theme={null}
{
  "error": {
    "code": "ORBY_SESSION_EXPIRED",
    "message": "Orby session token has expired — mint a new one.",
    "status": 401
  },
  "meta": {
    "request_id": "req_orby_012",
    "timestamp": "2026-09-09T12:34:05.119Z"
  }
}
```

## 1. Session-token failures

Every tool Orby runs is dispensed against a short-lived session token minted
at the start of the turn. When that token cannot be verified, the turn refuses
work with one of five codes. In practice the dashboard mints and refreshes
these tokens automatically, so you normally meet these codes only through the
[Orby API](/api-reference/orby) driven from your own client, or when a session
was revoked underneath you.

| Code                       | HTTP | Cause                                                                                                                                                                                                    | Fix                                                                                                                                                                                            |
| -------------------------- | ---- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ORBY_SESSION_REQUIRED`    | 403  | The request was authenticated with an API key (`X-API-Key` or a `dv_*` Bearer token) instead of a signed-in dashboard session. Orby is operator-facing only — there is no server-to-server API-key path. | Call Orby with the operator's dashboard session token (`Authorization: Bearer <dashboard JWT>`). If your integration only holds an API key, there is nothing to retry — switch the credential. |
| `ORBY_SESSION_MALFORMED`   | 401  | The session token could not be decoded: it is not three base64url segments, its header is not HS256, its payload is not JSON, or its issued-at is missing or future-dated.                               | Treat the token as corrupt and mint a fresh one (the dashboard does this on the next turn; a custom client requests a new turn token). Do not retry the same token string.                     |
| `ORBY_SESSION_SIG_INVALID` | 401  | The signature check failed — the token was tampered with, truncated, or signed under a different secret.                                                                                                 | Discard the token and mint a fresh one. If you copied the token out of a browser session by hand, re-take it in full — a clipped Bearer value is the usual cause.                              |
| `ORBY_SESSION_EXPIRED`     | 401  | The session token outlived its 15-minute TTL. Long idle gaps between turns are the common cause.                                                                                                         | Start a new turn — the dashboard mints a fresh token automatically. A custom client should treat this as "re-login" and continue on the same thread.                                           |
| `ORBY_SESSION_REVOKED`     | 401  | Every session token minted before the operator was offboarded (or before "End all Orby sessions" was clicked) is rejected on next verify.                                                                | Sign back in and start a new session. Teammates cannot revive a revoked token; a fresh session is the only path.                                                                               |

Sample envelope — a revoked session on `POST /api/v1/orby/assistant`:

```json theme={null}
{
  "error": {
    "code": "ORBY_SESSION_REVOKED",
    "message": "Orby session token was revoked (operator offboarded or session reset).",
    "status": 401
  },
  "meta": {
    "request_id": "req_orby_041",
    "timestamp": "2026-09-09T12:40:11.442Z"
  }
}
```

**Retry safety.** None of the session codes is retriable with the same token —
they all re-fail deterministically. The retry that works is always "new token,
same message."

## 2. Tool authorization

Three codes guard what a turn is allowed to do once the token has verified.
They look similar but fire at different gates, and the fix differs.

| Code                       | HTTP | Cause                                                                                                                                                                                                                                                         | Fix                                                                                                                                                                                                                     |
| -------------------------- | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ORBY_TOOL_CLAIM_MISSING`  | 401  | The session token decoded but carries no `tools` claim (or a non-array claim) — the per-turn allowlist is absent, so dispatch fails closed. This is a claim-shape failure, not a permissions failure.                                                         | Start a new turn so a fresh token is minted with the claim populated. If it recurs on every turn, escalate — a mint-time defect, not something an operator can fix.                                                     |
| `ORBY_TOOL_NOT_AUTHORIZED` | 403  | The tool Orby tried to run passed the registry and role checks but is absent from this turn's signed allowlist — the registry reloaded mid-turn, or a stale token re-dispatched against a newer tool set.                                                     | Retry the turn once — a fresh token re-scopes the allowlist to the current registry. If the same tool name keeps hitting the gate, narrow the request to the action you actually want and escalate with the request id. |
| `ORBY_TOOL_FORBIDDEN`      | 403  | The execute-time gate: approving a pending action re-checks the allowlist at redemption time, and the tool is no longer in scope — usually because the approval came after a role change, an offboarding, or a registry update between proposal and approval. | Re-ask Orby for the action (a new proposal mints a new scope) and approve it promptly. Pending actions expire after 5 minutes; do not sit on a card across a role change.                                               |

The distinction that matters: **`ORBY_TOOL_CLAIM_MISSING` means the token's
shape is wrong** (no allowlist at all — fail closed), while
**`ORBY_TOOL_NOT_AUTHORIZED` and `ORBY_TOOL_FORBIDDEN` mean the token is
well-formed but this specific tool is outside its scope** — the first at
dispatch time, the second at approval-redemption time.

Sample envelope — an out-of-scope tool at dispatch time:

```json theme={null}
{
  "error": {
    "code": "ORBY_TOOL_NOT_AUTHORIZED",
    "message": "Tool 'pause_campaign' is not in the session token's tools claim.",
    "status": 403
  },
  "meta": {
    "request_id": "req_orby_058",
    "timestamp": "2026-09-09T12:47:22.803Z"
  }
}
```

**Retry safety.** Retry once with a fresh turn. All three codes are
deterministic for a given token — re-sending the identical token re-hits the
same gate.

## 3. Rate, cost, and turn limits

| Code                     | HTTP            | Cause                                                                                                                                                                                                          | Fix                                                                                                                                                                                                                |
| ------------------------ | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `ORBY_RATE_LIMITED`      | 429             | The turn endpoint allows 60 turns per minute per operator.                                                                                                                                                     | Honor the `Retry-After` header (seconds) and re-send the same message — the turn is retriable as-is. If you script against the API, back off instead of polling in a tight loop.                                   |
| `ORBY_COST_CAP_EXCEEDED` | 429             | Reserved for a turn aborted because a tenant/session spend cap was reached. Spend-side exhaustion surfaces today as `AGENT_DAILY_SPEND_CAP_REACHED` (treated below); this code is kept for SDK enum stability. | If you meet `AGENT_DAILY_SPEND_CAP_REACHED` instead, see [spend-cap refusals](/troubleshooting/spend-caps-hit) — raise or reset the daily cap, then retry.                                                         |
| `ORBY_ITERATION_LIMIT`   | SSE error event | The turn chained through the iteration cap without converging — Orby kept calling tools (or re-reading data) without settling on an answer.                                                                    | Split the request into smaller questions and ask again. A single question that chains many lookups is the usual trigger; two narrower turns both succeed.                                                          |
| `ORBY_TURN_FAILED`       | SSE error event | Catch-all: the turn aborted without a narrower code — the pending-action intercept failed, or an unexpected exception surfaced mid-turn.                                                                       | Retry once. Read the accompanying `message` first — when the runtime knows more, it propagates it (`OPERATOR_PROMPT_BLOCKED`, spend-cap codes). If the message is empty, collect the `request_id` and escalate.    |
| `ORBY_LLM_FAILED`        | SSE error event | The model call itself failed — provider overload, a provider-side fault, or the in-flight call aborted against the turn deadline.                                                                              | Check the [status page](https://status.orbit.devotel.io), wait a few seconds, and retry. If sustained, the fallback is per-agent model pinning for your own agents; for Orby itself, retry with a shorter message. |

Sample SSE tail — a rate-limited turn:

```
event: error
data: {"code": "ORBY_RATE_LIMITED", "message": "Orby turn rate limit (60/min) exceeded — retry in 12s.", "status": 429}

event: done
data: {"ok": false}
```

**Retry safety.** `ORBY_RATE_LIMITED`, `ORBY_TURN_FAILED` (once), and
`ORBY_LLM_FAILED` are the retriable set. `ORBY_ITERATION_LIMIT` re-fails on
the identical prompt — change the request before retrying.

## 4. Knowledge-base readiness

Orby grounds "where do I configure X" answers in the indexed Orbit
documentation corpus. Two codes cover that index.

| Code                      | HTTP   | Cause                                                                                                                                                                     | Fix                                                                                                                                                                                                                                                                                                 |
| ------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ORBY_KB_NOT_INDEXED_YET` | 503    | The documentation index is cold — initialising, in maintenance, or not yet seeded after a deploy.                                                                         | Defer and retry: the [docs search endpoints](/api-reference/orby#knowledge-base-search) already degrade to an empty result with a `kb_outage_hint` instead of erroring, so the panel keeps working; ask Orby again once the index warms. A super-admin can confirm on `GET /api/v1/orby/kb/status`. |
| `ORBY_KB_REINDEX_FAILED`  | varies | Reserved for a failed documentation re-index. Not currently emitted by any route — a cold index surfaces as `ORBY_KB_NOT_INDEXED_YET` above. Kept for SDK enum stability. | None needed today; if a re-index you triggered with `POST /api/v1/orby/kb/reindex` (super-admin) shows no progress on the status endpoint, collect the request id and escalate.                                                                                                                     |

**Retry safety.** `ORBY_KB_NOT_INDEXED_YET` is transient — retry with
backoff; nothing about your query needs to change.

## 5. Thread ownership

| Code                    | HTTP | Cause                                                                                                                                                                                                          | Fix                                                                                                                                                                                                                                                   |
| ----------------------- | ---- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ORBY_THREAD_NOT_OWNED` | 403  | You referenced a `thread_id` that belongs to a different organization — cross-tenant access is refused. A thread id pasted from a teammate or from another workspace is the usual cause.                       | Use your own `thread_id` (or omit it to start a new thread). Note the sibling: a thread in your own organization but owned by a different operator returns `403 INSUFFICIENT_PERMISSIONS` — Orby threads are private to their operator, never shared. |
| Degraded thread list    | 200  | Not an error: on a brief store outage the thread list and reopen-a-thread reads degrade to the empty shape instead of failing, so the panel shows an empty list rather than an error page. Nothing is deleted. | Wait for the store to recover and reload — your threads come back. Distinguish this from `ORBY_THREAD_NOT_OWNED`: a 200 with an empty list is the degrade; a 403 is the ownership gate.                                                               |

Sample envelope — cross-workspace thread id:

```json theme={null}
{
  "error": {
    "code": "ORBY_THREAD_NOT_OWNED",
    "message": "Orby thread is owned by a different organization — cross-tenant access refused.",
    "status": 403
  },
  "meta": {
    "request_id": "req_orby_073",
    "timestamp": "2026-09-09T13:02:33.781Z"
  }
}
```

**Retry safety.** Ownership codes are deterministic — no retry helps; the fix
is always a thread you own.

## When to escalate

Escalate to support when:

* `ORBY_TOOL_CLAIM_MISSING` recurs on fresh turns — the mint path is broken,
  not your request.
* `ORBY_TOOL_NOT_AUTHORIZED` or `ORBY_TOOL_FORBIDDEN` keeps firing on the same
  well-scoped request after a fresh turn.
* `ORBY_SESSION_SIG_INVALID` appears on tokens the dashboard minted itself
  (you never touched the token by hand).
* `ORBY_LLM_FAILED` persists after the status page reports all operational.
* `ORBY_KB_NOT_INDEXED_YET` lasts longer than a maintenance window.

Include the `request_id` from the `meta` block (or the `error` SSE event), the
thread id when one exists, and the tool name for the `ORBY_TOOL_*` codes. The
request id threads through the turn, tool-dispatch, and approval paths, so
support can pull the executor-side trace without a back-and-forth.

## See also

* [Orby operator assistant architecture](/concepts/orby-operator-assistant) —
  the session-token mint, the tool registry, and the approval gate these codes
  guard.
* [Orby Assistant API](/api-reference/orby) — endpoint shapes, SSE events, and
  the rate-limit table.
* [Error reference](/reference/error-codes) — the full code catalog.
* [Using Orby in the dashboard](/guides/orby-in-dashboard) — the operator
  workflow on top of these endpoints.
* [Agent runtime errors](/troubleshooting/agent-errors) — the customer-facing
  agent sibling of this runbook (`AGENT_*` codes, not `ORBY_*`).
