Skip to content

fix: Validate first yielded value in orchestrator run() method#164

Open
YunchuWang wants to merge 2 commits intomainfrom
copilot-finds/bug/validate-first-yield-in-orchestrator-run
Open

fix: Validate first yielded value in orchestrator run() method#164
YunchuWang wants to merge 2 commits intomainfrom
copilot-finds/bug/validate-first-yield-in-orchestrator-run

Conversation

@YunchuWang
Copy link
Member

Summary

Add validation that the first value yielded by an orchestrator generator is a Task instance, matching the existing validation in
esume().

Closes #160

Problem

un() silently accepts any value (null, undefined, plain objects, primitives) as the first yield and assigns it to _previousTask without validation. This causes orchestrations to hang indefinitely with no error when a non-Task value is yielded.

Fix

Add the same instanceof Task validation that
esume() already has, replacing the TODO comment that acknowledged this gap.

The run() method in RuntimeOrchestrationContext did not validate that the
first value yielded by an orchestrator generator is a Task instance. The
resume() method already validates subsequent yields with an instanceof
check, but run() silently accepted non-Task values (null, undefined,
plain objects, primitives), causing the orchestration to hang indefinitely
with no error message.

This adds the same validation to run() that already exists in resume(),
throwing a clear error when a non-Task value is yielded. This also
removes the now-addressed TODO comment and the redundant instanceof
guard on the isComplete check.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 11, 2026 18:24
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a runtime correctness gap in the Durable Task JS orchestration engine by validating that the first value yielded by an orchestrator generator is a Task, aligning run() behavior with the existing validation in resume() to prevent silent orchestration hangs (Issue #160).

Changes:

  • Add instanceof Task validation for the first yielded value in RuntimeOrchestrationContext.run(), throwing a clear error on invalid yields.
  • Simplify the “already complete” check after the first yield now that _previousTask is guaranteed to be a Task.
  • Add Jest coverage to verify orchestrations fail (not hang) when the first yield is null, undefined, an object, or a primitive.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
packages/durabletask-js/src/worker/runtime-orchestration-context.ts Adds first-yield Task validation in run() to match resume() and prevent silent hangs.
packages/durabletask-js/test/orchestration_executor.spec.ts Adds tests ensuring invalid first yields fail the orchestration with an informative error.

You can also share your feedback on Copilot code review. Take the survey.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[copilot-finds] Bug: First yielded value in orchestrator run() is not validated, causing silent hangs

2 participants