Skip to content

fix(openai realtime): reject pending response future on error event#1384

Merged
toubatbrian merged 1 commit intomainfrom
claude/quirky-galileo-QffLi
May 5, 2026
Merged

fix(openai realtime): reject pending response future on error event#1384
toubatbrian merged 1 commit intomainfrom
claude/quirky-galileo-QffLi

Conversation

@toubatbrian
Copy link
Copy Markdown
Contributor

Summary

Ports livekit/agents#5576 (by @longcw) to agents-js.

When the OpenAI Realtime API sends an error event whose error.event_id matches the event_id of a response.create we issued, we now reject the pending future created by RealtimeSession.generateReply() instead of leaving it hanging. Without this, callers awaiting generateReply() 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 exists comment that was previously inside handleError.

What changed

  • plugins/openai/src/realtime/realtime_model.tsRealtimeSession.handleError:
    • Look up event.error.event_id in responseCreatedFutures.
    • If a CreateResponseHandle is registered for that id, remove it and reject its doneFut with an Error carrying event.error.message (only if the future has not already been settled).
    • The existing 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).
    • Removed the obsolete // TODO(brian): set error for response future if it exists comment.
  • .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:

Python (livekit-agents) JS (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 lookup
if not fut.done(): fut.set_exception(...) if (!handle.doneFut.done) handle.doneFut.reject(...)

Notable points:

  1. RealtimeError type does not yet exist in agents-js. It is referenced in JSDoc on agents/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 plain Error(event.error.message). Awaiters that previously hung on generateReply() will now observe a rejected promise carrying the OpenAI error message — same observable behavior as the Python change. Introducing a typed RealtimeError class can be done as a follow-up without changing this fix.
  2. Storage shape. Python stores raw asyncio.Future objects; JS wraps the future inside a CreateResponseHandle (because the JS handle also carries instructions). The reject targets handle.doneFut, which is the analog of the Python future.
  3. Atomic pop. Python uses dict.pop(event_id, None) for an atomic look-up-and-remove. JS does a separate lookup → delete, which is safe here because all responseCreatedFutures mutations happen from the single-threaded event-handler path.
  4. Ordering. Python rejects the future before calling _emit_error. The JS port matches that ordering, so any synchronous listeners on the error event 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.
  • Manual check: trigger a response.create that the realtime API rejects (e.g. invalid instructions) and confirm generateReply() 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

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-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 4, 2026

🦋 Changeset detected

Latest commit: 476c678

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 29 packages
Name Type
@livekit/agents-plugin-openai Patch
@livekit/agents-plugin-anam Patch
@livekit/agents-plugin-cartesia Patch
@livekit/agents-plugin-cerebras Patch
@livekit/agents-plugin-deepgram Patch
@livekit/agents-plugin-elevenlabs Patch
@livekit/agents-plugin-google Patch
@livekit/agents-plugin-inworld Patch
@livekit/agents-plugin-neuphonic Patch
@livekit/agents-plugin-resemble Patch
@livekit/agents-plugin-rime Patch
@livekit/agents-plugin-sarvam Patch
@livekit/agents-plugin-xai Patch
@livekit/agents Patch
@livekit/agents-plugin-assemblyai Patch
@livekit/agents-plugin-baseten Patch
@livekit/agents-plugin-bey Patch
@livekit/agents-plugin-hedra Patch
@livekit/agents-plugin-lemonslice Patch
@livekit/agents-plugin-liveavatar Patch
@livekit/agents-plugin-livekit Patch
@livekit/agents-plugin-minimax Patch
@livekit/agents-plugin-mistral Patch
@livekit/agents-plugin-mistralai Patch
@livekit/agents-plugin-phonic Patch
@livekit/agents-plugin-runway Patch
@livekit/agents-plugin-silero Patch
@livekit/agents-plugin-trugen Patch
@livekit/agents-plugins-test Patch

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

@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 2 additional findings.

Open in Devin Review

@toubatbrian toubatbrian merged commit ba3ffd5 into main May 5, 2026
8 of 9 checks passed
@toubatbrian toubatbrian deleted the claude/quirky-galileo-QffLi branch May 5, 2026 05:41
@github-actions github-actions Bot mentioned this pull request May 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants