Skip to content

[copilot-finds] Bug: Missing non-Task validation in resume() isFailed path causes silent generator state corruption #161

@github-actions

Description

@github-actions

Problem

In RuntimeOrchestrationContext.resume() (packages/durabletask-js/src/worker/runtime-orchestration-context.ts, lines 148-166), when the previous task has failed and the generator catches the thrown exception, there is no validation that the generator yields a Task object.

If the orchestrator catches an exception and yields a non-Task value:

async function* myOrchestrator(ctx) {
  try {
    yield ctx.callActivity(someActivity);
  } catch {
    yield "not a task"; // Bug: should fail with clear error
  }
}

The code silently falls through, leaving _previousTask pointing to the old failed task. On the next resume() call, the same exception is thrown to the generator in an unexpected location, causing confusing behavior.

Root Cause

The isComplete path (line 184-186) correctly validates the generator output:

if (!(value instanceof Task)) {
  throw new Error("The orchestrator generator yielded a non-Task object");
}

The isFailed path (lines 159-166) lacks this same validation:

if (throwResult.value instanceof Task) {
  this._previousTask = throwResult.value;
  if (this._previousTask.isComplete) {
    await this.resume();
  }
  return;
}
// <-- Falls through silently when value is not a Task

Proposed Fix

Add the same non-Task validation error after the instanceof Task check in the isFailed path, matching the existing validation in the isComplete path.

Impact

Severity: Medium. When an orchestrator yields a non-Task value after catching an exception from a failed task:

  • Instead of a clear "yielded a non-Task object" error, the orchestration enters an inconsistent state
  • On the next event, the same exception is re-thrown to the generator in an unexpected location
  • The resulting error message is confusing and does not indicate the actual problem (the non-Task yield)

This primarily affects orchestrators that catch task failures and have a programming error in their catch handler.

Metadata

Metadata

Assignees

No one assigned

    Labels

    copilot-findsFindings from daily automated code review agent

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions