openclaw - 💡(How to fix) Fix Bug: Twilio voice-call can get stuck in hold music after failed/no-stream call

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

A failed or incomplete Twilio inbound voice-call attempt can leave the voice-call Twilio provider believing a media stream is still active. The next inbound call is then routed into the built-in queue/hold path and plays Twilio hold music instead of connecting to the voice stream.

Error Message

After one inbound call was accepted and a call record was created, no MediaStream connected log appeared. A later inbound call heard hold music.

Root Cause

A later inbound call should not be routed to hold music because of a stale no-stream/failed-stream previous call.

Fix Action

Fix / Workaround

Notes

This appears separate from local testing patches around aborting stale response-model runs on caller barge-in. Those patches touched response generation/runtime abort plumbing, not Twilio's activeStreamCalls/queue/hold-music logic.

Code Example

[voice-call] Inbound call accepted: +17146238306 is in allowlist
[voice-call] Created inbound call record: b63fd8ac-7a1f-4321-9540-3aafeaa9f5ac from +17146238306

---

[MediaStream] Stream started ...
[voice-call] Media stream connected ...

---

if (input.direction === "inbound") {
  if (input.hasActiveStreams) return { kind: "queue" };
  if (input.canStream && input.callSid) return {
    kind: "stream",
    activateStreamCallSid: input.callSid
  };
  return { kind: "pause" };
}

---

if (decision.activateStreamCallSid) this.activeStreamCalls.add(decision.activateStreamCallSid);

---

<Response>
  <Say voice="alice">Please hold while we connect you.</Say>
  <Enqueue waitUrl="/voice/hold-music">hold-queue</Enqueue>
</Response>
RAW_BUFFERClick to expand / collapse

Bug: Twilio inbound voice-call can get stuck in hold music after failed/no-stream call leaves activeStreamCalls stale

Summary

A failed or incomplete Twilio inbound voice-call attempt can leave the voice-call Twilio provider believing a media stream is still active. The next inbound call is then routed into the built-in queue/hold path and plays Twilio hold music instead of connecting to the voice stream.

Observed behavior

After one inbound call was accepted and a call record was created, no MediaStream connected log appeared. A later inbound call heard hold music.

Recent logs showed:

[voice-call] Inbound call accepted: +17146238306 is in allowlist
[voice-call] Created inbound call record: b63fd8ac-7a1f-4321-9540-3aafeaa9f5ac from +17146238306

No corresponding:

[MediaStream] Stream started ...
[voice-call] Media stream connected ...

Then a later call was accepted but the caller heard the plugin's hold music. Twilio showed the later call completed, but OpenClaw did not log a stream connection/transcript for it.

Why this appears to happen

In the built Twilio provider, inbound TwiML policy queues new inbound calls whenever activeStreamCalls.size > 0:

if (input.direction === "inbound") {
  if (input.hasActiveStreams) return { kind: "queue" };
  if (input.canStream && input.callSid) return {
    kind: "stream",
    activateStreamCallSid: input.callSid
  };
  return { kind: "pause" };
}

generateTwimlResponse() then sets active state as soon as it returns stream TwiML:

if (decision.activateStreamCallSid) this.activeStreamCalls.add(decision.activateStreamCallSid);

But if Twilio never successfully opens the WebSocket media stream, or the stream setup fails before registerCallStream / unregisterCallStream lifecycle runs, the call SID can remain in activeStreamCalls. The next inbound call then gets QUEUE_TWIML:

<Response>
  <Say voice="alice">Please hold while we connect you.</Say>
  <Enqueue waitUrl="/voice/hold-music">hold-queue</Enqueue>
</Response>

/voice/hold-music plays Twilio's default classical hold track (BusyStrings.mp3).

Expected behavior

If an inbound call is given stream TwiML but the media stream never connects within a short timeout, the provider should clear that call SID from activeStreamCalls.

A later inbound call should not be routed to hold music because of a stale no-stream/failed-stream previous call.

Suggested fix

Add a guard/TTL around activeStreamCalls entries that are added during TwiML generation:

  • When activateStreamCallSid is added, start a short timer.
  • Clear the call SID if no media stream is registered/started within N seconds.
  • Clear the timer when the stream actually connects/registers.
  • Also clear on terminal call status callbacks where possible.

Alternatively, for single-call/no-queue configurations, consider disabling the queue path or making queueing configurable.

Environment

  • OpenClaw / @openclaw/voice-call: 2026.5.7
  • Provider: Twilio inbound voice-call streaming
  • Public URL via Tailscale Funnel
  • Streaming STT provider: Speaches
  • Voice-call webhook was reachable and returned valid TwiML when tested with a signed Twilio-style POST after the issue.

Notes

This appears separate from local testing patches around aborting stale response-model runs on caller barge-in. Those patches touched response generation/runtime abort plumbing, not Twilio's activeStreamCalls/queue/hold-music logic.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

If an inbound call is given stream TwiML but the media stream never connects within a short timeout, the provider should clear that call SID from activeStreamCalls.

A later inbound call should not be routed to hold music because of a stale no-stream/failed-stream previous call.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix Bug: Twilio voice-call can get stuck in hold music after failed/no-stream call