> ## 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: queue capacity gates

> Diagnose 503 QUEUE_DEPTH_CAP_REACHED on queue entry, 422 overflow-chain errors on queue config writes, and waiting-call vs. backpressure-cap readings — raise the cap, unbreak the overflow chain, or drain with callback-offer.

# Troubleshooting: queue capacity gates

A voice queue can refuse a caller at three different gates: the tenant-set
depth cap on the active queue (`QUEUE_DEPTH_CAP_REACHED`), the overflow
chain validation that runs when you write queue config
(`OVERFLOW_QUEUE_NOT_FOUND`, `OVERFLOW_QUEUE_CHAIN_CYCLE`,
`OVERFLOW_QUEUE_SELF_CHAIN`), and a re-prioritise attempt on an entry that
is no longer waiting (`QUEUE_ENTRY_NOT_QUEUED`). This page maps each
refusal to its gate and the fix. For a plain "callers stack up but agents
are staffed" problem instead, compare the chart on
[Reading queue state](#recognize-the-signal) before diving into config.

## Recognize the signal

The clearest signal of a cap firing is a `503 QUEUE_DEPTH_CAP_REACHED`
from `POST /api/v1/voice/queues/{id}/enqueue` or from the live-call
transfer-to-queue path — even though the agent wallboard still shows
available agents. The gate is depth-based, not staffing-based: the queue
ran past its depth cap, so enqueue refused the new caller instead of
accepting more FIFO depth that would only stretch wait and abandon
counters.

Read it from the response envelope, which carries the live numbers:

```json theme={null}
{
  "error": {
    "code": "QUEUE_DEPTH_CAP_REACHED",
    "status": 503,
    "message": "Target queue is at its depth cap; transfer rejected. Retry shortly or pick a less-loaded queue.",
    "details": { "queue_id": "queue_supp", "depth": 500, "max_depth": 500 }
  }
}
```

Confirm the numbers with two reads:

* `GET /api/v1/voice/queues/{id}/stats` — current waiting depth and
  longest wait.
* Organization settings — the tenant-set cap on `acd_queue_max_depth`
  (default 500; an unset or non-numeric value falls back to the
  default).

A separate **backpressure threshold** (200 waiting callers) drives the
wallboard's "approaching cap" alarm. A tenant-set cap lower than the
threshold is clamped to `200 + 1` so the alarm can never fire after the
hard cull — the warning always arrives before the refusal.

## Cause table

| Signal                                                   | Cause                                                                                                                                                       | Fix                                                                                                                                            |
| -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `503 QUEUE_DEPTH_CAP_REACHED` on enqueue                 | The queue's current waiting depth met the tenant-set `acd_queue_max_depth` cap                                                                              | Raise the per-org cap in organization settings, accept the caller into a less-loaded sibling queue, or drain depth with callback-offer (below) |
| `422 OVERFLOW_QUEUE_NOT_FOUND` on a queue config write   | The `overflowQueueId` on the queue's `overflowAction: "overflow_queue"` or `childQueue` chain does not resolve to a queue in this tenant (stale/deleted id) | Point `overflowQueueId` at an existing queue id and re-send the config write                                                                   |
| `422 OVERFLOW_QUEUE_CHAIN_CYCLE` on a queue config write | The overflow chain you are configuring loops back to itself (A → B → A, or a longer cycle)                                                                  | Break the loop; a chain must terminate on voicemail, callback, or a non-cycling queue                                                          |
| `422 OVERFLOW_QUEUE_SELF_CHAIN` on a queue config write  | `overflowQueueId` equals the queue's own id                                                                                                                 | Route the overflow to a sibling queue instead of self-chaining                                                                                 |
| `409 QUEUE_ENTRY_NOT_QUEUED` on re-prioritise            | The entry you tried to re-score already left the FIFO — dispatched to an agent, overflowed, or terminated between the entry-lookup and the write            | Read the entry's current state first; re-prioritise only `state: "queued"` entries                                                             |

Three of those are **enqueue-path gates** — the refusal tells the caller
"not now"; the others are **config-validation gates** — the refusal tells
you "your queue config cannot be saved in this state."

## Fixes

### 1. Raise the queue depth cap

The cap is tenant-owned. Set it on the organization settings field
`acd_queue_max_depth` — the value is floored to an integer, clamped to
stay above the wallboard backpressure threshold (200), and falls back to
the default of 500 when the field is unset or non-numeric. Raise it when
your inbound profile has documented bursty calling windows, lower it when
you want overflow to fire earlier.

```bash theme={null}
curl -X PATCH "https://api.orbit.devotel.io/api/v1/voice/queues/queue_supp" \
  -H "Authorization: Bearer $ORBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "overflowAction": "childQueue", "overflowQueueId": "queue_support_overflow" }'
```

The `PUT /api/v1/voice/queues/{id}` write lets you move a queue's
overflow config at the same time. Prefer raising the active cap for the
queues you staff, draining toward voicemail or callback for the ones
you do not.

### 2. Break the overflow chain cycle / unbreak the chain target

Overflow-chain rejections surface on **queue config writes**, not on
enqueue: the API refuses to persist a queue whose overflow chain would
silently misroute (`OVERFLOW_QUEUE_NOT_FOUND`) or loop the caller
forever (`OVERFLOW_QUEUE_CHAIN_CYCLE`, `OVERFLOW_QUEUE_SELF_CHAIN`).
Identify the broken queue id from the response `details`, then re-write
that queue with an `overflowQueueId` that resolves to a queue in the
tenant and does not close a cycle.

### 3. Drain depth with callback-offer

When the queue keeps breaching its SLA and the cap keeps firing, route
the hardest-breaching queue into the virtual-callback offer before it
hits the cap. A queue with
[slaCallbackPolicy `suggest` or `block`](/voice/queue-sla-forecast-callback)
diverts qualifying new callers into a "press 1 to keep your place and get
a callback" consent flow instead of accruing real hold. The abandoned-
callback rescue (`abandonedCallbackRescueEnabled`, tuned with
`callbackMaxAttempts` + `callbackRetryIntervals`) drains the callers who
already hung up back into callback dispatch. Both are queue-level knobs
you can wire on the same `PUT /api/v1/voice/queues/{id}` write — read
the full field inventory on the
[forecast + callback gate page](/voice/queue-sla-forecast-callback).

## Decision checklist

Work the gate in this order:

1. **Read the response code.** A `503` means the active queue's depth
   cap fired; a `422` on config write means the queue config was invalid
   (overflow-chain problem); a `409` means the entry no longer exists in
   FIFO.
2. **Check `GET /api/v1/voice/queues/{id}/stats`.** If waiting depth is
   under the threshold but the cap fires, your org's
   `acd_queue_max_depth` setting is the gate. If depth reads far under
   the cap but staffing is idle too, the gate is dispatch eligibility
   (skills, presence) — work it on the
   [voice queues guide](/guides/voice-queues).
3. **Check the queue's overflow chain.** `GET
   /api/v1/voice/queues/{id}` and confirm the `overflowQueueId` still
   resolves and the chain cannot loop.
4. **Choose one fix.** Raise the cap, fix the chain's target, or wire
   callback-offer. Do not raise the cap as a substitute for staffing —
   a queue at 500 waiting callers with two idle agents has a dispatcher
   problem the cap will never rescue.

## What not to do

* **Do not self-chain overflow.** A queue whose `overflowQueueId`
  points to itself loops callers on the second max-wait expiry — and
  the API refuses the write with `OVERFLOW_QUEUE_SELF_CHAIN` anyway.
* **Do not paper over a cap with a bigger cap.** The
  backpressure clamp exists so "cap too low" is never silently worse
  than the wallboard alarm expects. Raise the cap only after you read
  the queue's real depth and staffing; otherwise the cull still fires,
  just later.
* **Do not re-prioritise without a state read.** A `409
  QUEUE_ENTRY_NOT_QUEUED` is not a config bug — the entry left FIFO
  before the write sequenced. Read the entry first; if it is not
  `queued`, stop and check the dispatcher's outcome.
* **Do not blame the platform for tenant-owned config.** The depth cap,
  the overflow-chain target, and the callback policy are all set by your
  queue config; the API only enforces what the queue declares.

## Escalate

If every diagnostic above reads clean and enqueue still refuses callers:

* capture the HTTP **request\_id** from the response envelope plus the
  exact endpoint (`POST /api/v1/voice/queues/{id}/enqueue` or the
  transfer-to-queue call),
* include a `GET /api/v1/voice/queues/{id}/stats` snapshot and the
  queue config from `GET /api/v1/voice/queues/{id}`,
* send those to support with the tenant's organization name — the
  operator will drill into the dispatcher's counters on the live queue
  if the config and stats disagree.

## See also

* [Voice queues guide](/guides/voice-queues) — the full operator surface:
  create, enroll, priority, stats, alert rules, emergency override.
* [The ACD queue model](/concepts/acd-queue-model) — how enqueue,
  dispatch, skills, presence, and max-wait fit together end to end.
* [Per-queue SLA breach alerting and escalation policies](/voice/queue-sla-escalation-policies)
  — the queue's SLA objective ladder, the sibling surface that pairs
  with the cap.
* [Inbound queue SLA forecast + virtual callback gate](/voice/queue-sla-forecast-callback)
  — the callback-offer path that drains a breaching queue before the
  cap has to fire.
* [Error codes](/reference/error-codes) — the full set of refusal codes
  this page reads from.
