Skip to content

[copilot-finds] Bug: newOrchestrationState drops failure details when error message or type is empty string #187

@github-actions

Description

@github-actions

Problem

The newOrchestrationState function in packages/durabletask-js/src/orchestration/index.ts silently drops FailureDetails when either the error message or error type is an empty string.

File: packages/durabletask-js/src/orchestration/index.ts (lines 21-28)

The function uses falsy string checks to determine whether to create FailureDetails:

const failureDetailsErrorMessage = state?.getFailuredetails()?.getErrormessage();
const failureDetailsErrorType = state?.getFailuredetails()?.getErrortype();

if (state && failureDetailsErrorMessage && failureDetailsErrorType) {
  // ...
}

Since empty strings ("") are falsy in JavaScript, any TaskFailureDetails with an empty error message or error type is silently dropped. The returned OrchestrationState has failureDetails === undefined even when the orchestration has failed.

This function is called by getOrchestrationState(), waitForOrchestrationStart(), and waitForOrchestrationCompletion() on TaskHubGrpcClient.

Additionally, the stack trace extraction uses .toString() instead of the canonical .getValue() method used in every other call site in the codebase.

Root Cause

JavaScript falsy semantics: "" (empty string) is falsy, so the condition failureDetailsErrorMessage && failureDetailsErrorType fails when either field is an empty string. The protobuf getErrormessage() method returns "" by default for string fields, making this a realistic scenario.

Proposed Fix

Replace the falsy string checks with a null check on the TaskFailureDetails protobuf object itself, matching the pattern already used in client.ts (line 1261) and history-event-converter.ts (line 504):

const protoFailureDetails = state?.getFailuredetails();
if (protoFailureDetails) {
  failureDetails = new FailureDetails(
    protoFailureDetails.getErrormessage(),
    protoFailureDetails.getErrortype(),
    protoFailureDetails.getStacktrace()?.getValue(),
  );
}

Also fix getStacktrace()?.toString()getStacktrace()?.getValue() for consistency.

Impact

  • Severity: Medium-high. Failure details are silently lost for failed orchestrations with empty error messages, preventing debugging and hiding error information from the user.
  • Affected scenarios: Any orchestration that fails with throw new Error(""), throw new Error(), or any error whose .message property is an empty string. The orchestration status still shows FAILED, but state.failureDetails is undefined, so the user cannot inspect error type, stack trace, or 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