Skip to content

fix(ai-orchestration): observe agentStream output before draining#986

Merged
tombeckenham merged 1 commit into
TanStack:taren/workflow-orchestration-rfcfrom
tombeckenham:tom/fix-agentstream-unhandled-rejection
Jul 24, 2026
Merged

fix(ai-orchestration): observe agentStream output before draining#986
tombeckenham merged 1 commit into
TanStack:taren/workflow-orchestration-rfcfrom
tombeckenham:tom/fix-agentstream-unhandled-rejection

Conversation

@tombeckenham

Copy link
Copy Markdown
Contributor

🎯 Changes

Targets #979's branch, not main.

executeAgent awaited drainAgentStream() before result.output. When the stream fails, drain throws and the already-in-flight output promise is never observed — leaving a rejected promise unhandled. Under Node's default --unhandled-rejections=throw that terminates the worker, so an ordinary model error took down the process in addition to correctly failing the step.

Reproduced against the real workflow-core runtime before fixing:

unhandled rejections: 1 [ 'Error: output never observed' ]
events: [ 'RUN_STARTED', 'STEP_STARTED', 'STEP_FAILED', 'RUN_ERRORED' ]

The fix attaches a no-op catch to output as soon as the result is recognized, then awaits it after draining. Behaviour on the success path is unchanged.

Also adds the first test coverage for agentStream() — it was exported from index.ts but had no unit or E2E exercise, which is why this path went unnoticed. The test asserts both halves: the step fails with AgentStreamError, and no unhandled rejection escapes. Verified it fails without the source change.

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested this code locally with pnpm run test:pr.

🚀 Release Impact

  • This change is docs/CI/dev-only (no release).

@tanstack/ai-orchestration is still unreleased (0.0.0) and #979 already carries a minor changeset introducing the package. This fixes code from that same unreleased changeset, so a second changeset would only add noise. Happy to add one if you'd rather it be itemised.

`executeAgent` awaited `drainAgentStream()` before `result.output`. When the
stream failed, drain threw and the already-in-flight `output` promise was
never observed, leaving a rejected promise unhandled. Under Node's default
`--unhandled-rejections=throw` that terminates the worker — so an ordinary
model error took down the process in addition to failing the step.

Attach a no-op catch to `output` as soon as the result is recognized, then
await it after draining.

Adds the first coverage for `agentStream()`, asserting both that the step
fails with `AgentStreamError` and that no unhandled rejection escapes.
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a86acdaf-962f-44d0-84d8-5e16ad8f6dc2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@tombeckenham tombeckenham added the waiting-on: maintainer The ball is in the maintainers’ court label Jul 23, 2026
@tombeckenham
tombeckenham merged commit 53cc0b7 into TanStack:taren/workflow-orchestration-rfc Jul 24, 2026
3 checks passed
@tombeckenham
tombeckenham deleted the tom/fix-agentstream-unhandled-rejection branch July 24, 2026 03:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

waiting-on: maintainer The ball is in the maintainers’ court

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants