fix(openai realtime): reject pending response future on error event#1384
Merged
toubatbrian merged 1 commit intomainfrom May 5, 2026
Merged
fix(openai realtime): reject pending response future on error event#1384toubatbrian merged 1 commit intomainfrom
toubatbrian merged 1 commit intomainfrom
Conversation
When the OpenAI Realtime API sends an `error` event referencing the `event_id` of a `response.create` we issued, resolve the future created by `generateReply()` with an Error so awaiters do not hang. Ports livekit/agents#5576. https://claude.ai/code/session_01DgYvBGHayjKh6MfV763she
🦋 Changeset detectedLatest commit: 476c678 The changes in this PR will be included in the next version bump. This PR includes changesets to release 29 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
|
theomonnom
approved these changes
May 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Ports livekit/agents#5576 (by @longcw) to agents-js.
When the OpenAI Realtime API sends an
errorevent whoseerror.event_idmatches theevent_idof aresponse.createwe issued, we now reject the pending future created byRealtimeSession.generateReply()instead of leaving it hanging. Without this, callers awaitinggenerateReply()could block indefinitely on a request that the server has already failed.Closes the parity gap left by the
// TODO(brian): set error for response future if it existscomment that was previously insidehandleError.What changed
plugins/openai/src/realtime/realtime_model.ts—RealtimeSession.handleError:event.error.event_idinresponseCreatedFutures.CreateResponseHandleis registered for that id, remove it andrejectitsdoneFutwith anErrorcarryingevent.error.message(only if the future has not already been settled).emitError(...)call to surface the API error to listeners is preserved and now runs after the future is rejected, matching the Python ordering (set exception → emit error).// TODO(brian): set error for response future if it existscomment..changeset/openai-realtime-reject-pending-response.md— patch bump for@livekit/agents-plugin-openai.Implementation nuances vs Python
The behavior is equivalent, but there are a few naming/typing differences worth calling out:
livekit-agents)agents-js)self._response_created_futures: dict[str, asyncio.Future]this.responseCreatedFutures: { [id: string]: CreateResponseHandle }fut.set_exception(llm.RealtimeError(message))handle.doneFut.reject(new Error(message))dict.pop(event_id, None)delete this.responseCreatedFutures[eventId]after lookupif not fut.done(): fut.set_exception(...)if (!handle.doneFut.done) handle.doneFut.reject(...)Notable points:
RealtimeErrortype does not yet exist in agents-js. It is referenced in JSDoc onagents/src/llm/realtime.ts(@throws RealtimeError on Timeout) but no class is exported. Rather than expand the public API surface in this port, we reject the future with a plainError(event.error.message). Awaiters that previously hung ongenerateReply()will now observe a rejected promise carrying the OpenAI error message — same observable behavior as the Python change. Introducing a typedRealtimeErrorclass can be done as a follow-up without changing this fix.asyncio.Futureobjects; JS wraps the future inside aCreateResponseHandle(because the JS handle also carriesinstructions). The reject targetshandle.doneFut, which is the analog of the Python future.dict.pop(event_id, None)for an atomic look-up-and-remove. JS does a separatelookup → delete, which is safe here because allresponseCreatedFuturesmutations happen from the single-threaded event-handler path._emit_error. The JS port matches that ordering, so any synchronous listeners on theerrorevent will see the future already rejected.Test plan
pnpm build— full monorepo build succeeds (30/30 tasks).pnpm --filter @livekit/agents-plugin-openai lint— no new warnings introduced by this change.response.createthat the realtime API rejects (e.g. invalid instructions) and confirmgenerateReply()rejects with the server's error message instead of hanging.Provenance
Automated port created by @toubatbrian's Claude Code routine (experimental).
cc @toubatbrian @livekit/agent-devs
https://claude.ai/code/session_01DgYvBGHayjKh6MfV763she
Generated by Claude Code