Skip to main content

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 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:
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

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.
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 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.

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.
  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