Skip to content

[copilot-finds] Bug: setCustomStatus with non-serializable value crashes executor and loses orchestration result #190

@github-actions

Description

@github-actions

Problem

setCustomStatus() stores the raw object without serialization, and getCustomStatus() calls JSON.stringify() lazily. The problem is that getCustomStatus() is called outside the executor's try-catch block in orchestration-executor.ts (line 112):

try {
  // ... process events (setCustomStatus called here) ...
} catch (e: unknown) {
  ctx.setFailed(e instanceof Error ? e : new Error(String(e)));
}

// OUTSIDE try-catch — getCustomStatus() can throw here
return {
  actions,
  customStatus: ctx.getCustomStatus(), // JSON.stringify can throw!
};

If a user passes a non-serializable value to setCustomStatus() (e.g., an object with circular references, or containing BigInt), JSON.stringify() throws a TypeError that is not caught by the executor. This causes the entire orchestration execution result to be lost — the sidecar never receives the completion actions, leaving the orchestration stuck.

Affected files

  • packages/durabletask-js/src/worker/runtime-orchestration-context.ts (lines 406-418)
  • packages/durabletask-js/src/worker/orchestration-executor.ts (line 112)

Root Cause

Lazy serialization in getCustomStatus() defers JSON.stringify() to a point in the execution flow that is not protected by error handling. The executor's try-catch at lines 69-88 only covers event processing (where orchestrator code runs), not the result construction at lines 110-113.

Proposed Fix

Serialize eagerly in setCustomStatus() so that any serialization error is thrown inside orchestrator code (which runs within the executor's try-catch). Store the pre-serialized JSON string so getCustomStatus() becomes a trivial getter that cannot throw.

This ensures:

  1. Non-serializable values cause a clear error caught by the executor
  2. The orchestration properly fails with a descriptive error message
  3. The orchestration result is never silently lost

Impact

Severity: High — orchestration results are completely lost when this bug triggers.

Affected scenarios:

  • Setting custom status with an object containing circular references
  • Setting custom status with an object containing BigInt values
  • Setting custom status with an object whose toJSON() method throws

Without the fix, the orchestration appears stuck (sidecar never receives completion). With the fix, the orchestration properly fails with a clear "Custom status value is not JSON-serializable" error message.

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