[Fix] 020-twilio-media-streams-node — register Twilio handler before Deepgram connect#93
Conversation
…t in 020-twilio-media-streams-node The Twilio WebSocket message handler was registered after awaiting dgConnection.waitForOpen(), causing early media events to be lost if the Deepgram connection took any time to establish. Now the handler registers immediately and buffers audio until the Deepgram socket is ready. Also uses sendCloseStream (SDK v5 convention) and wraps waitForOpen in try/catch to prevent unhandled rejections. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Code ReviewOverall: CHANGES REQUESTED Integration genuineness✓ Pass — Same Twilio integration as #89; the fix is to the same file and addresses the same race condition. Code quality
Documentation
Tests
Conflicts
RecommendationPR #89 is the more thorough fix. This PR should be closed in favor of #89, or substantially reworked to avoid the issues noted above. Please address the items above. The fix agent will pick this up automatically. Review by Lead on 2026-04-01 |
Fix assessmentFinding: PR #89 ( Recommendation: This PR should be closed in favor of #89, per the review feedback. The issues noted in review (double @deepgram-devrel — Recommending this PR be closed in favor of #89 which is the more complete fix and has already passed review. Fix by Lead on 2026-04-01 |
Code ReviewOverall: CHANGES REQUESTED Integration genuineness✓ Pass — Fix PR for existing Twilio integration. The existing codebase already integrates with Twilio media streams. Code quality
Documentation
Tests
Conflict with PR #89PR #89 and this PR (#93) fix the same bug. PR #89 is more complete:
Recommend closing this PR in favor of #89. Please address the items above. The fix agent will pick this up automatically. Review by Lead on 2026-04-01 |
- Remove unused twilio import - Close twilioWs after stop event - Update to SDK v5 connect() method (replaces deprecated createConnection) - Fix double sendCloseStream by only sending in stop handler, not close handler - Update test to close WS after stop to match real Twilio behavior
Fix appliedRoot cause: Review feedback identified unused import, missing twilioWs close on stop, deprecated createConnection() API, double sendCloseStream, and test not closing WS after stop. Change:
Tests will re-run automatically. Fix by Lead on 2026-04-01 |
Code ReviewOverall: CHANGES REQUESTED Integration genuinenessPass — fix PR for existing Twilio integration. Twilio integration remains genuine. Code quality
NotePR #89 addresses the same root cause with a more robust approach:
Recommend merging PR #89 instead of this one. Tests
Please address the items above. The fix agent will pick this up automatically. Review by Lead on 2026-04-01 |
Code ReviewOverall: CHANGES REQUESTED Integration genuinenessPass — This is a fix PR for the existing Twilio media streams example. Integration is real. Code quality
DocumentationN/A — fix PR. Tests
NotesThis PR overlaps significantly with PR #89, which addresses the same root cause with a slightly cleaner approach (synchronous handler + async IIFE). The Please address the items above. The fix agent will pick this up automatically. Review by Lead on 2026-04-01 |
- Make WS handler synchronous; wrap Deepgram setup in async IIFE with .catch() - Add sendCloseStream before dgConnection.close() in close handler - Remove unused twilio dependency from package.json
Fix appliedRoot cause: Review feedback identified missing Change: (1) Made WS handler synchronous and wrapped Deepgram setup in an async IIFE with Tests will re-run automatically. Fix by Lead on 2026-04-01 |
|
@deepgram-devrel — VP escalation: this PR has been stuck after 3 fix attempts. Root cause unclear. Manual review needed. State: labels=[type:fix], no E2E check status, no review-passed label Last activity: 2026-04-01T06:28:40Z |
Code ReviewOverall: APPROVED Integration genuinenessPass — Fix PR for the existing 020-twilio-media-streams-node example. The Twilio integration is genuine in the base example. Code quality
DocumentationN/A — fix PR. Tests
NotesThis PR now addresses all previous review feedback. However, it overlaps with PRs #89 and #95 which fix the same root cause. Only one should be merged — recommend merging the earliest approved PR (#89) and closing the others. ✓ All checks pass. Marking review passed. Review by Lead on 2026-04-01 |
Code ReviewOverall: APPROVED Integration genuinenessPass — bug-fix PR for existing Twilio integration. Addresses the same async race condition as PRs #89 and #95, with a slightly different approach (flushes buffered audio from the Code quality
NotePRs #89, #93, and #95 all fix the same root cause. Only one should be merged. This PR's approach of flushing from the ✓ All checks pass. Marking review passed. Review by Lead on 2026-04-01 |
Code ReviewOverall: APPROVED Integration genuinenessPass. Same analysis as PRs #89/#95 — fix PR for the Twilio Media Streams example. Twilio integration is at the protocol level. Code quality
Documentation
Tests
NotePRs #89, #93, and #95 all fix the same issue. PR #93's approach of flushing the buffer in the Review by Lead on 2026-04-01 |
Code ReviewOverall: CHANGES REQUESTED Integration genuineness
Code quality
Documentation
Tests
NotePRs #89, #93, and #95 all fix the same bug. This PR (#93) has the most robust Please address the items above. The fix agent will pick this up automatically. Review by Lead on 2026-04-01 |
…ilio-media-streams-node - Add twilio import and use twilio.twiml.VoiceResponse for TwiML generation - Restore twilio dependency in package.json 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Fix appliedRoot cause: Review requested restoring the Change: Added Tests will re-run automatically. Fix by Lead on 2026-04-01 |
Code ReviewOverall: CHANGES REQUESTED Integration genuinenessN/A — bug fix PR. Code qualityThe fix is correct — same root cause identification as #95 (async handler race condition). Minor differences: uses RecommendationPlease close this PR in favor of #95, which is a more complete version of the same fix. Please address the items above. The fix agent will pick this up automatically. Review by Lead on 2026-04-01 |
…audio (#95) ## Fix: 020-twilio-media-streams-node regression **Root cause:** The `app.ws('/media', async (twilioWs) => {...})` handler awaited `dgConnection.waitForOpen()` before registering `twilioWs.on('message', ...)`. Since `express-ws` does not await async handlers, early Twilio messages (`connected`, `start`, and `media` audio frames) arrived before the handler was registered and were silently dropped. No audio reached Deepgram, so no transcripts were returned, causing a 30-second timeout. ### Changes **`src/index.js`:** - Make WS handler synchronous — `express-ws` does not await async callbacks - Register Twilio `message`, `close`, `error` handlers immediately - Buffer incoming audio in `mediaQueue` until Deepgram connection is ready - Move Deepgram setup into an async IIFE with `.catch()` for error handling - Flush buffered audio once `waitForOpen()` resolves and `dgReady` is set - Use `sendCloseStream({ type: 'CloseStream' })` per SDK v5 convention (replaces deprecated `sendFinalize`) - Remove unused `twilio` import and dependency - Close Twilio WS after `stop` event (matches real Twilio behavior) **`tests/test.js`:** - Close test WebSocket 500ms after sending `stop` event (matches real Twilio client behavior) **`package.json`:** - Remove unused `twilio` dependency ### Test plan - [ ] CI runs test with real Deepgram credentials - [ ] Transcripts are received from spacewalk audio - [ ] No 30s timeout > Note: This fix supersedes PRs #89 and #93 which address the same root cause. --- *Fixed on 2026-04-01* --------- Co-authored-by: examples-bot <noreply@deepgram.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Luke Oliff <luke@lukeoliff.com>
Summary
await dgConnection.waitForOpen()to prevent early media events from being lostopeneventsendCloseStream({ type: 'CloseStream' })instead of deprecatedsendFinalize(SDK v5 convention)waitForOpen()in try/catch to prevent unhandled promise rejectionsRoot cause
The Twilio WebSocket message handler was registered after
await dgConnection.waitForOpen(). In SDK v5,createConnection()creates the socket withstartClosed: true, andconnect()+waitForOpen()initiates the actual WebSocket handshake asynchronously. During this window, Twilio sendsconnected,start, andmediaevents that were silently dropped because no handler was registered yet. By the time the handler was active, all audio had already been sent, resulting in zero transcripts and a 30s timeout.Test plan
POST /voicereturns TwiML with<Stream>pointing to/media🤖 Generated with Claude Code