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

# Diagnose a call

> Get a plain-English explanation of what happened on any call to your voice agent (failed, cut short, or completed) and what to fix.

Find why a call failed, ended early, had one-way audio or dropped its stream. After [logging in](https://plivo.com/docs/cli/install.md#log-in-with-a-browser), find the call's UUID (its unique identifier), then request an explanation:

```bash theme={null}
plivo voice calls list --limit 5                 # find the UUID
plivo voice calls diagnose "<call_uuid>"           # usually about a minute; allow 30 to 120 s
```

Replace `"<call_uuid>"` with an ID from the list. The diagnosis reports a timeline and likely causes involving your server, Plivo or the carrier. For voice agents, check the answer URL, its XML and the WebSocket connection.

A typical answer:

```text theme={null}
What happened: This inbound call was terminated because Plivo could not fetch call instructions from your answer URL.
Likely cause: The answer URL https://api.example.com/plivo/answer returned 404. The call was hung up with
              cause 7011 (Error Reaching Answer URL).
Timeline: 07:48:40.600 call received · 07:48:40.630 answer URL responded 404 · 07:48:41.016 call hung up
Suggested next step: Make sure the answer URL is deployed and returns Plivo XML with HTTP 200; every inbound call will fail until it does.
```

The hangup causes you will see most often while building a voice agent:

| Hangup cause | Meaning | Fix |
| - | - | - |
| `7011` Error reaching answer URL | Plivo could not fetch your answer URL (down, not public, tunnel closed, 4xx/5xx) | Check the URL is reachable from the internet; while developing, use [Forward calls to your voice agent](https://plivo.com/docs/cli/voice-agent/forward-calls.md) |
| `8011` Invalid answer XML | The answer URL returned something that is not Plivo XML (often JSON, or an HTML error page) | Return `<Response><Stream …>` with `Content-Type: application/xml`; check with `curl -X POST "<answer_url>"` |
| `4010` End of XML instructions | Normal end; your voice agent closed the WebSocket, or the XML finished | Only a problem if the call ended earlier than you expected: check your voice agent's logs for why it closed |
| `USER_BUSY` | A busy outcome; inspect the call record and XML to identify its source | Check whether your handler deliberately rejected the call before changing it |

If the answer URL and XML are valid but the caller hears silence, test the voice agent and its audio format without a phone with [Test your voice agent](https://plivo.com/docs/cli/voice-agent/test-websocket.md). For the raw record (hangup cause, source, duration) run `plivo voice calls get <call_uuid> -o json`, or `plivo open call <call_uuid>` to see the call and its Call Insights in the console. For a call over a SIP trunk, use `plivo sip calls diagnose` and `plivo sip calls insights`; see [Check and diagnose a SIP call](https://plivo.com/docs/cli/voice-agent/sip-diagnose-call.md).

## Read the result in a script

With `-o json` (or when output is piped), `diagnose` prints one JSON result when the analysis ends:

```bash theme={null}
plivo voice calls diagnose "<call_uuid>" -o json
```

```json theme={null}
{
  "data": {
    "call_uuid": "…",
    "what_happened": "…",
    "likely_cause": "…",
    "timeline": [ { "at": "…", "event": "…", "source": "…" } ],
    "next_steps": [ "…" ],
    "hangup_cause_code": 7011,
    "hangup_source": "…",
    "confidence": "high",
    "answer": "…"
  }
}
```

| Field | What it holds |
| - | - |
| `what_happened`, `likely_cause` | The assistant's explanation, in short sentences |
| `timeline[]` | Events in order, each with `at`, `event` and `source` |
| `next_steps[]` | What to do next |
| `hangup_cause_code`, `hangup_source` | Taken from the call record, not from the assistant; `null` for a message |
| `confidence` | `high`, `medium` or `low`; `null` when the answer gives none |
| `answer` | The full prose answer |

For a message the ID field is `message_uuid` instead of `call_uuid`. `-o yaml`, `-o csv` and `--query` work on this result, for example `--query 'data.likely_cause'`. `-o jsonl` streams the assistant's raw events instead of one result.

If the analysis fails, escalates or stops early, `diagnose` exits with code `3`, so a script can tell a finished analysis from one that didn't finish. Pass `--timeout <seconds>` to put a limit on a script's wait: an analysis still running at that point ends with `UPSTREAM_TIMEOUT` and exit code `3`. An unknown UUID exits `1` without using a request from your limit.

> [!NOTE]
>
> The answer is written by Plivo's AI assistant, so read the prose as an explanation; scripts should read the fields of the `-o json` result instead. `diagnose` and `plivo ask` share a limit of 5 requests per 60 seconds per account. Only calls on your own account can be diagnosed. For messages see [Diagnose a message](https://plivo.com/docs/cli/apis/messaging.md#diagnose-a-message); for general questions see [Get help](https://plivo.com/docs/cli/apis/help.md).
