Platform
ScaiWave ScaiGrid ScaiCore ScaiBot ScaiDrive ScaiKey Models Tools & Services
Solutions
Organisations Developers Internet Service Providers Managed Service Providers AI-in-a-Box
Resources
Support Documentation Blog Downloads
Company
About Research Careers Investment Opportunities Contact
Log in

Troubleshooting

Trunk parks in sync_status=error#

Symptom. You created or edited a trunk, but sync_last_error is set and sip_trunk_id is null.

First check: read the error message verbatim. livekit-sip's response usually tells you the real cause.

Carrier response Likely cause Fix
401 Unauthorized Wrong sip_auth_username or sip_auth_password Verify the credentials on the carrier's portal; the value you paste is the one ScaiDial REGISTERs with
403 Forbidden Source-IP whitelisting on the carrier rejects us Send your carrier the egress IP from GET /network-info
503 Service Unavailable Carrier upstream issue or our livekit-sip can't reach the address Check sip_server_address resolves; try POST /trunks/probe to test without persisting
408 Request Timeout Firewall is dropping our packets before they reach the carrier Same as 403 — egress IP whitelisting is the usual fix

After fixing the underlying cause, hit POST /trunks/{id}/resync — no need to recreate the trunk.

"No synced outbound trunk" on click-to-call (422)#

Symptom. The browser softphone shows "Your tenant has no synced outbound trunk."

Cause. Either no trunk exists for the tenant, or the only trunks are in sync_status="error" / "pending".

Fix. Open /scaidial/trunks and look at the sync-status badges. Either create a trunk or fix the synced one with the table above.

Calls ring but I can't hear anything#

This is almost always one of three things.

Browser mic permission denied. Open the browser's permission panel for the site. Reload after granting. The softphone publishes the mic on join — if getUserMedia fails, the room connects but no audio is sent.

Remote audio not autoplaying. Some browsers block autoplay if there hasn't been a recent user gesture. The click that originated the call counts, but if the call was initiated by a different tab or in a background context, autoplay may be blocked. Hit "Hang up" then "Place call" again, fresh.

SIP/RTP firewall. If livekit-sip can't get RTP back from the carrier, the SIP leg connects but the media path is dead. Verify your firewall lets UDP 10000-10200 (the RTP range) in and out. GET /network-info shows the exact range.

Inbound calls fail with "no_rule_matched"#

Symptom. Inbound call arrives, immediately gets end_reason=no_rule_matched.

Cause. The dialplan has no rule that matches this call. Common reasons:

  • All rules use time_window and the call is outside the window. Add an always fallback rule at priority 999.
  • The DID isn't wired to the dialplan you edited. Check GET /dids/{id} and verify dialplan_id.
  • The rule is enabled=false.

The dialplan engine logs the rules it evaluated and why each one didn't match. Look in the ScaiGrid structured logs for scaidial_dialplan_no_match with the call ID.

Voicemail has no transcript#

Symptom. The voicemail audio plays fine but transcript and summary are null.

Cause #1. Transcripts are opt-in per tenant. Go to /scaidial/settings and enable "Voicemail transcripts." Existing voicemails won't get transcripts retroactively; new ones will from the moment you enable.

Cause #2. The opt-in is on but the transcript hasn't materialised yet. ScaiEcho runs after the recording is finalised; it's a few seconds for short messages, longer for multi-minute messages.

Cause #3. ScaiEcho returned an error (most commonly: pyannote model not loaded on the inference node, which only affects diarization — plain transcripts should still work).

Transfer fails with 409#

Symptom. Clicking Transfer surfaces "transfer failed: ..." with status 409.

Causes:

  • Attended mode requested. v1 only supports blind transfer. The admin UI defaults to blind.
  • Carrier rejected the REFER. Not all carriers accept SIP REFER from the answering leg. Test with POST /trunks/probe and ask your carrier whether REFER is supported on outbound trunks.
  • Leg already ended. The other party hung up between when the transfer button rendered and when you clicked. The Active Calls page auto-refreshes every 4s; the window is small.

Browser softphone disconnects mid-call#

The store retries once after a transient drop. If it doesn't recover, the call card flips to error state with the disconnect reason.

If you see SERVER_SHUTDOWN, the LiveKit server (not livekit-sip — the SFU) was restarted. Calls survive controller restarts but not LiveKit-server restarts.

If you see network-level disconnects without server shutdown, check your WebRTC posture. The softphone uses LiveKit's default ICE — STUN servers + TURN if configured. If your network blocks UDP entirely, you need to configure a TCP TURN server.

"scaidial not initialized" 503#

Symptom. Per-leg control routes return 503.

Cause. The module registry constructed the ScaiDial module but its start() lifecycle hook hasn't completed yet. This is a startup window of a few seconds; it should clear by itself.

If it persists, check ScaiGrid logs for scaidial_start_failed — common causes are missing LiveKit cluster config (SCAIBOT_VOICE_LIVEKIT_URL/API_KEY/API_SECRET) or a livekit-sip sidecar that's not running. The Trunks page is still readable in this state; you just can't act on calls.

Where to look in the logs#

ScaiDial emits structured (key=value) events. The most useful keys for triage:

  • scaidial_inbound_dispatch_decision — every inbound INVITE, including the matched rule.
  • scaidial_outbound_originate — every click-to-call (or other admin originate).
  • scaidial_leg_state_change — leg state transitions; useful for figuring out where a call died.
  • scaidial_trunk_sync_failed — the carrier's actual response, in full.
  • scaidial_livekit_sip_* — anything wrong on the sidecar path.

Filter by correlation_id to follow a single call across components.

Updated 2026-06-23 01:06:32 View source (.md) rev 1