Troubleshooting: 409 NO_ELIGIBLE_AGENT on route to queue
Routing an unassigned ticket through a queue (Route to queue on the ticket, orPOST /api/v1/inbox/tickets/{id}/route-through-queue) asks the queue to pick an agent for the ticket right now: a queue member whose skills cover the queue’s required set, whose presence is available, and who has headroom under their per-channel concurrency cap. 409 NO_ELIGIBLE_AGENT means the queue exists but, at that instant, nobody in it passed those gates. The ticket stays unassigned; nothing about the conversation or the ticket changes. This page decodes the refusal, separates it from the automatic-assign overflow reasons, and walks the checks that fix it.
Everything below is tenant-owned configuration on digital queues and agent presence. A queue never touches provider or carrier behaviour, so the fix always lives in your workspace settings.
The 409 envelope and what it means
The refusal is a409 with error.code NO_ELIGIBLE_AGENT, and error.details carries the queue and the reason:
details.reason first:
Two adjacent refusals on the same call are different codes, not this one:
422 AGENT_CHANNEL_CAP_EXCEEDED means members matched skills and presence but every one of them sat at their per-channel concurrency cap for the ticket’s channel (a cap is a deliberate ceiling, so the cap case refuses rather than over-assigns); 409 ALREADY_ASSIGNED means the ticket already has an owner and must be reassigned explicitly instead.
The refusal is a routing decision, not a failure of the request itself: the queue was found and evaluated, and the answer was “nobody qualifies right now.”
Manual route vs automatic-assign overflow: different triggers, same root cause
A queue meets the same eligibility gates in two places, and the refusals read differently:- Manual route-to-queue (this page) is synchronous. It evaluates the gates once, at request time, and refuses with
409 NO_ELIGIBLE_AGENTwhen the pool is empty. There is no waiting set behind it: a manual route either assigns immediately or returns the 409. - Automatic assignment of inbound conversations is patient. When no eligible agent is free, the conversation joins the queue’s waiting set with an SLA deadline and keeps re-evaluating; it only sheds per the queue’s
overflow_action, and the shed reasons on that path arequeue_full(the waiting set reached max queue depth),sla_breached(the SLA deadline passed with still no eligible agent), andno_skilled_agents(nobody in the workspace holds the required skills, so waiting is pointless and the queue sheds immediately) — the overflow model is on Digital queues.
available presence, and per-channel headroom. The difference is trigger shape — the manual path reports the empty pool instantly as a 409, while the automatic path holds first and only names the condition as an overflow reason when holding can no longer help. So no_skilled_agents on the automatic path and NO_ELIGIBLE_AGENT on the manual path are the same underlying state seen from two surfaces, and the fix table below applies to both.
Read-state checks
Work these in order; each names where to look:- Required skills and minimum skill level. Open Inbox → Settings → Digital queues, edit the queue from
details.queue_id, and read Required skills and Minimum skill level. A member is eligible only when their profile covers every required skill at or above the minimum level; a single narrow skill nobody holds empties the pool. An empty required-skills list means any member is eligible. - Member enrollment. On the same form, confirm the queue actually has members, and that the agents you expect are listed with membership state
available. A queue whose roster is empty returnsno_membersbefore any skill check runs. - Presence. Eligibility requires live
availablepresence: an agent who isoffline,pausedfor the day, or on a voicebusy/wrapupleg is skipped. Read the team view (or Presence federation states when a presence badge looks wrong) and confirm at least one member isavailableat the moment you route. - Per-channel concurrency caps. Under Settings → Team → Channel concurrency caps, each agent has a ceiling per channel. Members who matched skills and presence but sit at the cap for the ticket’s channel produce
422 AGENT_CHANNEL_CAP_EXCEEDEDrather than this 409 — if that is the code you actually see, the fix is cap headroom, not skills. - Overflow action.
overflow_actiondoes not change this 409 — it governs what the automatic path does with a conversation the queue cannot place (routing_rules,overflow_queue,auto_responder,hold). You will want it set for the waiting-set side of the same root cause, but no overflow setting turns a manual-route 409 into an assignment. - Live stats cross-check.
GET /api/v1/inbox/digital-queues/statsreads the same state back per queue:backlogabove zero withagents_availableat zero is the skill/presence shape of this refusal; a positiveagents_availablewith a stuck backlog points at the per-channel cap instead.
Fixes
Match the cause you found to its fix:
Every fix except waiting on presence is a queue or team setting you own; none requires a provider change.
Do not blind-retry
An immediate repeat of the same route call evaluates the same state and returns the same 409 — the refusal is deterministic, not a transient fault, so a retry loop only repeats it. Retry is correct after a state change from the table above lands (an agent flips toavailable, a cap is raised, a skill list is widened); when you do retry, the assignment is atomic, so a route that loses a race against a concurrent assign returns 409 ALREADY_ASSIGNED — read the ticket’s assignee before routing again rather than re-firing.
See also
- Digital queues — skill match, SLA, overflow actions, and the live stats endpoints
- Inbox assignment and auto-close — the inbound
pending-lane decoder on the automatic path - Agent presence lifecycle — the presence states every eligibility gate reads