Why Your AI Voice Agent Call Dropped: Reason Codes - Zian AI

Why Your AI Voice Agent Call Dropped: Reason Codes

Three fields carry the answer: Vapi’s endedReason, Retell’s disconnection_reason, and Twilio’s call status plus SipResponseCode. We counted 597 unique endedReason values in Vapi’s published OpenAPI spec on 8 September 2026, against 34 Retell reasons and 8 Twilio call statuses. Same incident, three vocabularies. Start with the field name, not the symptom.

Why did my AI voice agent call drop? Find the field before you form a theory

Every managed voice platform writes a terminal code on the call record, and every platform uses a different name for the field and a different vocabulary inside it. Before you can diagnose anything you need the string itself, not a description of what the caller experienced:

  • Vapi writes endedReason on the Call object and shows it in the Ended Reason column of the call logs (Vapi, Call ended reasons).
  • Retell AI writes disconnection_reason, visible on the call in Call History or via the Get Call API (Retell, Debug call disconnection).
  • Twilio, sitting underneath both as a telephony carrier, writes a call Status and — on terminal status callbacks only — a SipResponseCode (Twilio, Call Resource).

The first thing the field usually tells you is that nothing went wrong. Twilio’s own documentation is explicit that A completed call indicates that a connection was established, and audio data was transferred. This can occur when a call is answered by a person, an IVR phone tree menu, or even a voicemail. A completed Twilio leg with a 12-second duration and a Vapi endedReason of customer-ended-call is not an incident. It is a person hanging up.

That ordering matters, because a working system produces expected-behaviour codes by design — customer-ended-call, user_hangup, assistant-ended-call, agent_hangup — and both Vapi and Retell classify those as normal endings rather than errors. Rule them out first, then work down the list below. We hold no cross-platform incidence data and could not locate a published dataset of it, so this page is ordered by the shape of the failure rather than by any claim about how often each one occurs.

The Rosetta table: Vapi endedReason, Retell disconnection_reason and Twilio status side by side

Every string in this table was read from the vendor’s own documentation or published API schema. Where we could not locate a published equivalent in that vendor’s own documentation or schema, the cell says so rather than guessing — an invented equivalence is worse than a gap, because it sends you to the wrong dashboard.

What happened Vapi endedReason Retell disconnection_reason Twilio status / SIP code Likely root cause Where to look next
Caller hung up customer-ended-call user_hangup completed Normal The last 20 seconds of transcript, not the logs
Agent hung up deliberately assistant-ended-call, assistant-said-end-call-phrase agent_hangup completed End-call tool fired, or an end-call phrase matched The end-call phrase list and the tool’s trigger conditions
Silence timeout silence-timed-out inactivity completed — no published equivalent located for the timeout itself The configured silence window elapsed with no speech detected Vapi silenceTimeoutSeconds; Retell end_call_after_silence_ms
Call hit its length cap exceeded-max-duration max_duration_reached completed — no published equivalent located Platform-side duration limit, not a fault Vapi maxDurationSeconds; Retell max call duration
Answered by voicemail voicemail voicemail_reached completed (Twilio documents voicemail as a completed call) Answering-machine detection fired, or was not configured Voicemail-detection settings on the assistant
Line busy customer-busy dial_busy busy Destination engaged Retry cadence, not configuration
Rang out customer-did-not-answer dial_no_answer no-answer; Twilio returns 487 when the call does not connect before the Timeout value elapses Nobody picked up inside the ring window The dial timeout, then the time of day you are calling
Number invalid or unreachable twilio-reported-customer-misdialed invalid_destination failed; Twilio returns 404 when the destination number is unreachable Malformed number, usually a formatting problem rather than a dead line E.164 formatting, then the provider’s route to that country
Carrier blocked the call as spam No published equivalent located marked_as_spam No published equivalent located in Twilio’s call status values Number reputation, typically after a volume spike with a low pickup rate Number warm-up, pickup rate, and branded-calling registration
SIP trunk rejected the call call.in-progress.error-providerfault-outbound-sip-403-forbidden telephony_provider_permission_denied SIP 403 Forbidden in response to your INVITE Credentials, IP allowlist, caller-ID permission or geographic permission The Via header on the 403 — Twilio documents its received parameter as showing the IP address the SIP request came from — then your trunk’s access control list
Concurrency ceiling hit call.start.error-subscription-concurrency-limit-reached concurrency_limit_reached Twilio documents 503 Trunk concurrent call limit exceeded on Elastic SIP Trunking Plan or trunk limit, not a fault in the agent Your plan’s concurrency allowance and your dialer’s pacing
Billing stopped the call before it started call.start.error-subscription-insufficient-credits, call.start.error-subscription-frozen no_valid_payment No published equivalent located Wallet, card or credit balance The billing page, before you debug anything else
Transfer failed call.in-progress.error-transfer-failed, call.in-progress.error-warm-transfer-silence-timeout transfer_cancelled (published for the transfer agent’s leg of an agentic warm transfer; no general transfer-failure reason located) No single status — the transfer becomes its own leg with its own status Bad destination, unsupported transfer scenario, or the destination not answering with audio The child leg in the provider’s call log, matched on the telephony call ID
Telephony provider closed the audio socket phone-call-provider-closed-websocket, call.in-progress.twilio-completed-call No published equivalent located completed with a non-zero duration The media path between the platform and the carrier broke Provider call timeline, compared timestamp-to-timestamp against the platform’s
No audio arriving from the caller call.in-progress.error-assistant-did-not-receive-customer-audio error_no_audio_received in-progress, then completed Network, microphone, or a caller who disconnected silently Whether the transcript is empty or merely stops
Platform-side process crashed call.in-progress.error-vapifault-worker-died, worker-shutdown error_retell completed on the carrier leg Vendor infrastructure; usually transient Retry, then escalate with the call ID if it recurs
Custom LLM never connected call.in-progress.error-pipeline-ws-model-connection-failed error_llm_websocket_open Not visible to the carrier Wrong URL, DNS, TLS, route mismatch, or nothing listening Your own server’s access log for the upgrade request
Custom LLM socket dropped mid-call call.in-progress.error-providerfault-custom-llm-llm-failed (generic custom-LLM failure; no socket-specific mid-call value located) error_llm_websocket_lost_connection Not visible to the carrier Keepalives stopped, or an idle timeout on a proxy in front of your server Your proxy’s WebSocket idle timeout; with Retell’s auto_reconnect enabled you must echo ping_pong within 5 seconds
Speech-to-text failed pipeline-error-deepgram-transcriber-failed and the equivalent per-provider strings error_asr Not visible to the carrier Transcriber credentials, quota, or a provider outage The transcriber provider’s status page and your key’s quota

Two things fall out of building this. First, the platforms agree almost perfectly on the boring rows — hang-ups, busy, no answer, voicemail, duration caps — and diverge completely on failures. Second, the direction of detail is not symmetrical: Vapi names the failing component and the responsible party in the string itself, while Retell keeps a short, stable list and pushes detail into the call’s detailed logs and PCAP file. Neither is better; they just require different next moves from you.

The triage flow: four failure shapes, four different next checks

A caller only ever reports one of four things. Each shape has a different first check, and running the wrong one costs you the incident window.

Branch 1 — Dead air: the line was open but nobody spoke

  1. Read the terminal code. If it is silence-timed-out or inactivity, the platform ended a call in which it detected no speech. Next check: the configured silence window, then whether the transcript is empty or merely truncated.
  2. If the transcript is empty and the code is call.in-progress.error-assistant-did-not-receive-customer-audio or error_no_audio_received, audio never reached the platform. Next check: the carrier leg’s duration — a long completed leg with no inbound media points at the media path, not the agent.
  3. If the transcript has caller turns but no agent turns, the pipeline broke on the way out. Next check: the code’s provider segment — a *-voice-failed, *-transcriber-failed or *-llm-failed string names which of the three services to open first. Long pauses that are not a failure are a different problem; see our note on what sub-second voice AI response times actually require.

Branch 2 — The agent hung up

  1. If the code is assistant-ended-call or agent_hangup, this was deliberate. Next check: the tool-call entry immediately before the end of the transcript.
  2. If it is assistant-said-end-call-phrase, a configured phrase matched. Next check: your end-call phrase list against the agent’s last utterance, looking for a phrase common enough to fire mid-conversation.
  3. If it is exceeded-max-duration or max_duration_reached, you hit a cap. Next check: the duration value on the call against the configured maximum — they should match to the second.
  4. If it is voicemail or voicemail_reached, answering-machine detection fired. Next check: the recording, to confirm it really was a machine.

Branch 3 — The transfer failed

  1. Confirm the platform actually initiated it. On Vapi, a successful hand-off is assistant-forwarded-call; anything else means the transfer never started. Next check: the transfer tool’s configuration, and whether call control has been handed to your own server.
  2. Confirm the scenario is supported. Vapi publishes a support matrix in which web-call-to-phone-number and PSTN-to-SIP transfers are listed as not supported. Next check: that matrix, against the leg types in your call.
  3. If the platform initiated it and the shape is supported, the failure is downstream. Next check: the child leg in the carrier’s call log, found by the telephony call ID on the platform’s call object — not by timestamp. What the human on the other end receives when it does work is a separate design problem, covered in our piece on carrying context through an AI-to-human handoff.
  4. For SIP trunks, the transfer is a REFER. Next check: whether a REFER left at all, and what the response to it was.

Branch 4 — The provider closed the socket underneath the call

  1. The signature is a partial transcript that stops mid-sentence with a non-zero duration and a transport-level code: phone-call-provider-closed-websocket, call.in-progress.twilio-completed-call, or call.in-progress.sip-completed-call. Next check: the carrier’s own timeline for that leg, because the carrier will show a normal completion where the platform shows a break.
  2. Distinguish it from a platform crash. call.in-progress.error-vapifault-worker-died and worker-shutdown are the platform’s own process ending, not the carrier’s. Next check: whether other calls in the same minute ended the same way — a deployment-shaped cluster looks different from a network-shaped single event.
  3. For custom LLM integrations, the socket that closed may be yours. Next check: the WebSocket close code in your server’s logs. Retell documents that a close code of 1000 from your side is treated as a deliberate hangup and ends the call as agent_hangup rather than as an error, which is how a server-side crash gets misfiled as a normal call.
  4. If the socket closed before any audio flowed on an inbound call, the problem is upstream of the agent entirely — see the checks in our guide to getting a phone line ready for an inbound AI caller.

The single most useful habit is recording the platform call ID and the telephony call ID together at the end of every call. Without the pairing, branch 3 and branch 4 both stall at the same place: you can see that the carrier did something, but you cannot find which leg it did it to.

Zian AI runs live phone, SMS, email and WhatsApp outreach through its own digital team agents, and reading these codes is part of running them. Zian is in a partnership-application beta.

Apply For Partnership

How big each vocabulary actually is, and how we counted

Counts matter here because they tell you how much of the diagnosis the vendor has pre-classified for you and how much you have to reconstruct. Method: on 8 September 2026 we fetched each vendor’s published machine-readable schema or documentation page and counted the enumerated values in the relevant field. No estimates, no rounding.

Platform Field Values counted Source counted
Vapi endedReason 629 entries, 597 of them unique The Call schema in the OpenAPI document at api.vapi.ai/api-json
Retell AI disconnection_reason 34 in the schema; 33 described in the docs table The DisconnectionReason enum in Retell’s Get Call API reference
Twilio call Status 8 The Call Status Values table on Twilio’s Call Resource page
Bland AI status and queue_status 6 and 9 Bland’s Call Details API reference
ElevenLabs Agents conversation status 5 ElevenLabs’ Get conversation details API reference

Three findings worth carrying away. The Vapi enum contains 32 duplicate entries — 629 listed values resolve to 597 distinct strings — so any count taken straight off the spec without deduplicating runs about 5% high. The Retell schema publishes one value, manual_stopped, that we did not find described in the documentation table. And the shape of the Vapi enum is itself diagnostic: 255 of the 597 distinct values (42.7%) begin pipeline-error-, while only 10 mention SIP and only 10 mention a transfer. A managed voice platform expects to fail at the model, voice and transcription layer far more variously than at the telephony layer — which is the opposite of where most teams start looking.

SIP response codes: the only vocabulary all of these platforms share

Underneath every one of these products is SIP, and SIP codes are the one layer that means the same thing everywhere. Vapi states this plainly in its Troubleshoot SIP response codes guide: Session Initiation Protocol (SIP) response codes describe the result of a SIP request. They are standard protocol responses, not Vapi-specific error codes. The same guide warns that Vapi does not have a code-specific endedReason for every SIP response, which is exactly why the mapping above has blanks in it.

SIP code RFC 3261 name What it usually means in a voice-agent incident First check
403 Forbidden The responding system understood the request and refused it Credentials, IP allowlist, caller-ID and geographic permissions
404 Not Found The number or SIP URI could not be resolved; Twilio returns this when the destination is unreachable Number formatting, then whether the provider has a route
407 Proxy Authentication Required A proxy is challenging; can be a normal step rather than a failure Whether an authenticated request followed the challenge
408 Request Timeout No response produced in time DNS, firewall rules, signalling ports and transport
480 Temporarily Unavailable Destination known but offline, unregistered or on do-not-disturb Endpoint registration and routing
484 Address Incomplete The dialled address is incomplete Country code and E.164 formatting
486 Busy Here Reached, but cannot take another call Nothing on your side; this is destination state
487 Request Terminated Cancelled before completion; Twilio returns this when its Timeout elapses Who sent the CANCEL, from the signalling trace
503 Service Unavailable Temporarily unavailable — and providers also use it for routing failures and call limits Trunk capacity, calls-per-second limits, and any Retry-After header

Names in the second column are as defined in RFC 3261 §21. The third and fourth columns follow the guidance Vapi publishes in its SIP response code guide and the quick reference Retell publishes for debugging SIP calls from a PCAP file. A practical consequence for anyone running volume: 503 from a trunk usually means a limit rather than an outage, and limits are a capacity-planning problem rather than an incident — the distinction we drew when writing about scaling from 100 to 10,000 calls a day.

Where the mapping runs out, and what we could not find

This is documentation mapping, so the gaps are part of the result.

  • ElevenLabs Agents. We could not locate a published enum of termination reasons. The Get conversation details API reference types termination_reason as a string with no allowed-values list — it sits inside the metadata object — while the top-level status field on the same response does publish five allowed values: initiated, in-progress, processing, done, failed. We looked at that reference page and at the documentation index at elevenlabs.io/docs/llms.txt.
  • Bland AI. The Call Details reference publishes six status values and nine queue_status values, but describes error_message only as a description of the error. We could not locate an enumerated list of those messages on that page or in the documentation index at docs.bland.ai/llms.txt; the page gives four examples of common failure text rather than a closed set.
  • Spam blocking. Retell publishes marked_as_spam. We could not locate an equivalent published value in Vapi’s endedReason enum or in Twilio’s call status values, having searched the 597 distinct Vapi strings and the Call Resource status table. Vapi’s call.start.error-fraud-check-failed is its own fraud detection blocking a call at start, which is a different event from a carrier refusing to deliver one.
  • Twilio and the pipeline. Nothing that happens to the model, voice or transcriber is visible to a carrier at all. The 255 pipeline-error- values alone — 43% of Vapi’s vocabulary — describe events Twilio has no way to represent.

The general rule the exercise produced: a code tells you which vendor’s dashboard to open next; it rarely tells you the cause. Treat the string as a router, not as a diagnosis, and the four-branch flow above as the thing that actually narrows it. More of how we work through evidence like this sits in the Zian AI questions and answers hub.

Frequently asked questions

Why did my AI voice agent call drop with no error code?

Because most terminal codes are not errors. Vapi groups customer-ended-call, assistant-ended-call, silence-timed-out, exceeded-max-duration and voicemail as expected behaviour, and Retell marks user_hangup, agent_hangup and inactivity the same way. Twilio adds a further trap: it documents that a completed call simply means a connection was established and audio was transferred, including when the answer was a voicemail or an IVR menu.

Does a SIP 487 mean the caller hung up?

Not necessarily — it means somebody cancelled. RFC 3261 §21.4.25 defines 487 Request Terminated as: The request was terminated by a BYE or CANCEL request. This response is never returned for a CANCEL request itself. In practice the CANCEL is often yours: Twilio’s Call Resource documentation states that if the call does not connect before the specified Timeout value elapses, the API returns 487. Read the signalling trace to see which side sent it before concluding the person rejected your call.

Is there a standard set of call-ended codes across voice AI platforms?

We could not locate one. Each platform publishes its own vocabulary in its own field name, and the counts are not comparable — 597 distinct values for Vapi against 34 for Retell is a difference in design philosophy, not in reliability. The only shared layer is SIP, and even there, Vapi notes it does not have a code-specific ended reason for every SIP response. We looked at Vapi’s, Retell’s, Twilio’s, Bland AI’s and ElevenLabs’ published documentation and API schemas on 8 September 2026.

How do I tell a silence timeout from a media failure?

By whether the platform heard anything at all. A silence timeout — silence-timed-out on Vapi, inactivity on Retell — means the timer expired with no speech detected, and the transcript will usually contain earlier turns. A media failure — call.in-progress.error-assistant-did-not-receive-customer-audio or error_no_audio_received — means audio stopped arriving after the connection was established, and the carrier leg will show a healthy duration with nothing to show for it. The two need opposite fixes: one is a settings change, the other is a network investigation.

What does phone-call-provider-closed-websocket mean?

Vapi documents it as the call provider’s WebSocket connection closing unexpectedly, with the caller experiencing an abrupt drop. The important property is that it is a statement about the audio path between the platform and the carrier, so the evidence lives in the carrier’s logs rather than in the assistant’s configuration. We could not locate a directly equivalent value in Retell’s published DisconnectionReason enum; its nearest published value, error_no_audio_received, describes media that stops arriving rather than a socket that closed.

Which field should I log for every call?

Three: the platform’s terminal code, the platform’s call ID, and the telephony provider’s call ID. Vapi exposes the last of these as phoneCallProviderId on the Call object. Without the pairing, a transfer failure or a carrier-side disconnect cannot be traced to the specific leg it happened on, and the diagnosis stalls at the point where you can see that something happened but not to what.

Zian AI builds autonomous AI sales agents — outbound appointment setters, 24/7 customer support agents in 30+ languages, and sales call closers — with SmartReach AI™ orchestrating channel and timing and PrecisionPitch AI™ split-testing the scripts. The platform is in a partnership-application beta.

Apply For Partnership

Related Blogs

Related from Zian AI