# SIP / RTP Debugging

> Debug the telephony leg: SIP signalling causes and Q.850, RTP loss and jitter, and registration failures.

When a phone call misbehaves, the fault is almost always in one of three places. The **signalling**: the call never sets up, or it tears down early. The **media**: the call connects, but the audio is bad or one-way. The **registration**: a trunk or a SIP phone cannot authenticate. This page is the field guide for all three. Start from the symptom. Read the likely cause. Apply the fix.

Every call keys off a single `call_sid`. When you have that from your reports, you can follow one call across signalling, media, and the agent. Pull the SIP ladder and the per-call quality numbers from the [call trace explorer](/modalities/voice/observability/call-traces) in the console before you start to guess.

> **NOTE:**
> This is the debugging reference. For the step-by-step guide for a trunk that does not come up at all, see [SIP Trunk Issues](/modalities/voice/troubleshooting/sip-trunk). For audio that flows only one way, see [One-Way Audio](/modalities/voice/troubleshooting/one-way-audio). For a call that never answers, see [Call Does Not Connect](/modalities/voice/troubleshooting/call-not-connecting).

## Where to look first

  1. **Get the call_sid**
Find the call in your reports and copy its `call_sid`. Every downstream tool is keyed on it: the SIP ladder, the media quality record, and the CDR.
  2. **Read the SIP ladder**
Open the [call trace explorer](/modalities/voice/observability/call-traces). Pull the full request/response ladder for that `call_sid`. Read the final response code and the `Reason` / Q.850 cause on the last message. They tell you whether signalling failed or the far end failed.
  3. **Read the media quality record**
Every call that reached the media plane has a per-call quality record: packet loss, jitter, and an MOS score computed from them. If signalling looks clean but callers complain, the answer is here. See [MOS, Jitter &amp; Packet Loss](/modalities/voice/observability/mos-jitter-loss).
  4. **Drop to packets only if needed**
If the summary numbers do not explain it, capture the raw SIP and RTP at the edge. See [Packet-Level Debugging](/modalities/voice/observability/packet-debugging).

## SIP signalling failures

The SIP gateway answers inbound calls as a back-to-back user agent (B2BUA). Thus it owns both legs of every dialog. A healthy inbound answer runs `100 Trying` → `183 Session Progress` **with SDP** (early media) → `200 OK` **with the same SDP** → `ACK`. Deviations from that sequence are the most common cause of "the call connected and then dropped."

### Symptom → cause → fix

| Symptom | Likely cause | Fix |
|---|---|---|
| The `INVITE` gets no response at all | The source IP does not match a trunk, or the source-IP ACL blocks it | Check that the carrier's signalling IP is on the trunk (trunks match by source IP or dialed DID). Check the ACL. See [SIP Trunk Issues](/modalities/voice/troubleshooting/sip-trunk). |
| The `INVITE` is answered `403 Forbidden` | The trunk/ACL rejected the source, or the spam filter tripped | Check the trunk's `internal_sip_ip` / source IP and realm. Review the spam-filter thresholds. |
| The `INVITE` is answered `404 Not Found` | The dialed DID is not provisioned or is not bound to a trunk/agent | Import the E.164 number. Bind it to a trunk and an agent. See [Number Provisioning](/modalities/voice/transport-telephony/number-provisioning). |
| `488 Not Acceptable Here` | Codec mismatch: the offered SDP had no codec that the engine will answer | Offer G.711 µ-law (PT 0) or A-law (PT 8). The engine transcodes to its internal bus, but the wire codec must be one that it accepts. See the [Codec Guide](/modalities/voice/transport-telephony/codecs). |
| The call answers, then the carrier sends `BYE` within ~1&nbsp;s | The provisional `180 Ringing` was sent **without** SDP, so there is no early-media path. Some carriers tear down | The engine answers with `183 Session Progress` that carries SDP for early media. Make sure that the carrier does not force an SDP-less `180`. |
| `487 Request Terminated` | The caller hung up (`CANCEL`) before answer. This is normal for abandoned calls | Usually benign. Correlate with the ring duration in reports. |
| `408 Request Timeout` / `480 Temporarily Unavailable` | The far leg (a human SIP phone, a PSTN callee, or a vendor) never responded | Check the destination endpoint's registration and reachability. See the registration section below. |
| `486 Busy Here` / `603 Decline` | The callee was busy or declined | Expected. It shows in the CDR as the mapped Q.850 cause. |
| `503 Service Unavailable` | The upstream trunk or vendor is congested or out of service | Retry over an alternate trunk. Check the carrier status. |
| The call drops mid-conversation with `BYE` | A session timer / re-`INVITE` was not honored, or media was inactive | Check for a stalled media path (see the RTP section). A dead media plane can trigger a teardown. |

### Q.850 cause codes

When a call clears, the gateway writes a CDR that includes the **Q.850 cause**: the PSTN-world reason the call ended, mapped from the final SIP response. Read the cause on the `cleared` event to classify a hang-up without a replay of the whole ladder. The common ones:

| Q.850 | Meaning | Typical SIP mapping | What it usually means |
|---|---|---|---|
| 16 | Normal call clearing | `BYE` / `200` | One of the parties hung up normally. |
| 17 | User busy | `486 Busy Here` | The callee was on another call. |
| 18 | No user responding | `408 Request Timeout` | The far leg never answered signalling. |
| 19 | No answer (user alerted) | `480` / `408` | The call rang out with no pickup. |
| 21 | Call rejected | `403` / `603` | An ACL, a policy, or a callee decline. |
| 27 | Destination out of order | `502` / `503` | The trunk or gateway is down. |
| 31 | Normal, unspecified | `480` / `404` | Catch-all clearing. |
| 34 | No circuit/channel available | `503` | Trunk congestion / capacity. |
| 38 | Network out of order | `503` | An upstream network fault. |
| 41 | Temporary failure | `503` | A transient upstream error. It is safe to retry. |
| 47 | Resource unavailable | `503` | No media or signalling resource. |
| 88 | Incompatible destination | `488` | A codec / capability mismatch. |
| 102 | Recovery on timer expiry | `408` | A timer (e.g. session refresh) fired. |
| 127 | Interworking, unspecified | varies | Cross-network mapping loss. |

> **TIP:**
> A CDR row for an AI-handled call has a handler tag on the segment. Thus you can tell whether the leg that cleared was the AI stretch or a human stretch of the same `call_sid`. Multi-segment calls split at the handoff. See [Observability Overview](/modalities/voice/observability/overview).

## RTP / media failures

The media plane runs RTP/RTCP in-engine. The wire codec is G.711 (µ-law PT 0 / A-law PT 8). The engine decodes it to the runtime's 8&nbsp;kHz PCM16 bus, applies noise suppression, and re-paces it back out every 20&nbsp;ms (160 samples per tick). It scores each call's quality from loss and jitter with an ITU-T G.107 E-model and writes an MOS estimate to the per-call quality record. DTMF rides as RFC&nbsp;2833 events.

### Reading the RTP stats

Two numbers do most of the work:

- **`packet loss`** (`percent`) — Computed from RTP sequence-number gaps. Sustained loss above ~1–2% is audible. Above ~5% the call is rough. Bursty loss (dropped runs of sequence numbers) sounds worse than the same average spread evenly, because the jitter buffer cannot conceal a long gap.
- **`jitter`** (`milliseconds`) — Inter-arrival variation. The jitter buffer absorbs a working range. Past that range, late packets are discarded (and counted as loss) or add delay. Jitter that rises together with discard-loss is a network-path problem, not a codec problem.

The MOS score folds both into one number. Thus you can rank calls without the raw counters. Treat MOS as the triage signal. Treat loss/jitter as the diagnosis. The full interpretation guide is [MOS, Jitter &amp; Packet Loss](/modalities/voice/observability/mos-jitter-loss).

### Symptom → cause → fix

| Symptom | Likely cause | Fix |
|---|---|---|
| Choppy / robotic audio, high loss % | Network loss on the RTP path, or bursty sequence gaps | Check the path to the carrier. Capture RTP at the edge to see the gaps. See [Packet-Level Debugging](/modalities/voice/observability/packet-debugging). |
| Delayed audio, a "walkie-talkie" feel, high jitter | Jitter is past the buffer's working range, so the buffer discards late packets | Reduce the path jitter. Sustained high jitter shows as discard-loss and a low MOS. |
| **One-way audio** (the caller cannot hear the agent, or the reverse) | RTP flows in only one direction. The usual cause is NAT/addressing: a private bind IP is advertised where a public IP is required | Check the trunk's `external_rtp_ip` (public) vs `internal_rtp_ip` (bind). In cloud-NAT, the SDP must advertise the public media address. See [One-Way Audio](/modalities/voice/troubleshooting/one-way-audio). |
| No audio at all, but the call is `established` | The SDP negotiated a codec that the far end never sends, or media never opened | Check that the answered SDP codec matches the wire. Check that the call resolved to `proxy` media mode. The runtime requires proxied media for AI handling and recording. |
| DTMF digits are not detected | The digits are sent as in-band audio tones instead of RFC&nbsp;2833 events | Configure the carrier/endpoint to send RFC&nbsp;2833 (telephone-event) DTMF. |
| Pitch too high or too low ("chipmunk") | A sample-rate mismatch across a leg (for example, an 8&nbsp;kHz leg treated as 16&nbsp;kHz) | This class of double-resample bug is fixed in the stateful resampler. If you see it on a bridged/vendor leg, check the leg's declared clock rate. |
| MOS is good but the agent mishears speech | Not a transport problem. This is turn-taking or recognition | Move to the runtime side: [Barge-In Debugging](/modalities/voice/observability/barge-in-debugging). |

> **WARNING:**
> `media_mode: direct` is defined on the trunk, but the live runtime degrades it to `proxy` now. If you configured `direct` and see no recording, no MOS, and no AI audio, that is why. Proxied media is the working path. See [Transport to Telephony Overview](/modalities/voice/transport-telephony/overview).

## Registration failures

The engine embeds its own SIP registrar. It is on by default and multidomain. It uses digest auth plus a source-IP ACL, with nonce/replay hardening. There is no separate registration server to run. Two kinds of party register: **outbound trunks** that register to a carrier, and **human agents on real SIP deskphones/softphones** that register to your workspace. Each workspace has its own SIP host, `<workspace-id>.sip.firstbyte.fast`. The engine identifies the tenant from the leftmost DNS label of the inbound request.

### Symptom → cause → fix

| Symptom | Likely cause | Fix |
|---|---|---|
| `REGISTER` is challenged `401 Unauthorized` in a loop | Wrong digest credentials, or the client does not re-send with the `Authorization` header after the nonce challenge | Check the AOR user and secret (secrets are sealed at rest). A single `401` challenge is normal. A *loop* means the credential response is wrong. |
| `REGISTER` is answered `403 Forbidden` | The source IP is not on the SIP ACL, or the realm/domain is wrong | Add the device's IP to the SIP ACL. Check that it registers to the correct `<workspace-id>.sip.firstbyte.fast` realm. |
| `REGISTER` is answered `404` / `488` | The client registers to the wrong tenant subdomain, so the leftmost label does not resolve to your workspace | Point the SIP client at `<workspace-id>.sip.firstbyte.fast` exactly. The label *is* the tenant key. |
| The phone registers, then goes unreachable after a minute or two | The registration `Expires` is too short and the client does not refresh | Make sure that the client re-registers before expiry. The binding TTL follows the `Expires` value. |
| An inbound call to a registered phone never rings it | The Contact is bound to a private/NAT address that the engine cannot reach | The engine binds on a private IP but must advertise a reachable Contact/Via. Check public vs private addressing for cloud-NAT. |
| The trunk does not register outbound to the carrier | Wrong `sip_username` / `sip_password` or `register_expires_sec`, or the carrier expects a specific transport (WS/WSS) | Check the trunk credentials and transport (`sip_ws` vs `sip_wss`/TLS). See [SIP Trunk Issues](/modalities/voice/troubleshooting/sip-trunk). |

> **TIP:**
> Trunk `INVITE`s bypass the registrar ACL. They match by source IP instead. Thus a trunk can deliver calls even while a *device* registration fails. Do not conflate the two. Registration problems affect SIP phones and outbound trunk registration. Inbound carrier trunks match by IP.

## A quick triage flow

  1. **Did the call set up?**
No final `200 OK` in the ladder → **signalling**. Read the final response and the Q.850 cause above. If the trunk never came up, go to [SIP Trunk Issues](/modalities/voice/troubleshooting/sip-trunk).
  2. **Did it set up but sound bad or go one-way?**
The call is `established` but the audio is poor → **media**. Read loss/jitter/MOS. For one-way audio, check the RTP addressing. Go to [One-Way Audio](/modalities/voice/troubleshooting/one-way-audio) or [MOS, Jitter &amp; Packet Loss](/modalities/voice/observability/mos-jitter-loss).
  3. **Is it a device or trunk that won't come up?**
`REGISTER` fails → **registration**. Check the credentials, the ACL, the tenant subdomain, and the expiry above.
  4. **Still stuck?**
Capture the raw packets at the edge and read the wire directly. Go to [Packet-Level Debugging](/modalities/voice/observability/packet-debugging).

## Related

  - **[SIP Trunk Issues](/modalities/voice/troubleshooting/sip-trunk)** — The focused runbook for a trunk that does not register or route.
  - **[MOS, Jitter &amp; Packet Loss](/modalities/voice/observability/mos-jitter-loss)** — How to read the media quality metrics that this page points you at.
  - **[Packet-Level Debugging](/modalities/voice/observability/packet-debugging)** — When the summaries are not enough, read the SIP and RTP off the wire.
  - **[Call Lifecycle](/modalities/voice/transport-telephony/call-lifecycle)** — The healthy INVITE-to-CDR sequence that these failures deviate from.
