Skip to content

[copilot-finds] Bug: newFailureDetails() drops error.cause chain, losing inner exception information #210

@github-actions

Description

@github-actions

Problem

The newFailureDetails() function in packages/durabletask-js/src/utils/pb-helper.util.ts (line 188) converts JavaScript errors into protobuf TaskFailureDetails messages but never populates the innerFailure field, even when the source error has a .cause property.

The protobuf TaskFailureDetails message has a recursive innerFailure field specifically designed to preserve error chains:

message TaskFailureDetails {
    string errorType = 1;
    string errorMessage = 2;
    google.protobuf.StringValue stackTrace = 3;
    TaskFailureDetails innerFailure = 4;
    bool isNonRetriable = 5;
}

However, setInnerfailure() is never called anywhere in the codebase.

Root Cause

The newFailureDetails() function extracts name, message, and stack from the error but does not check for error.cause (the ES2022 standard for error chaining).

Impact

The codebase creates errors with { cause: ... } in 9+ places (client.ts, entity-executor.ts, pb-helper.util.ts). When these errors are reported as orchestration/activity failures, the inner cause information is completely lost. This makes debugging harder because:

  • parseJsonField wraps SyntaxError in a descriptive error with { cause: err } — the original parse error is lost
  • Client operations (rewind, restart) wrap gRPC errors with { cause: e } — the original gRPC error details are lost
  • Entity state serialization errors wrap the original error — the cause is lost

Cross-SDK impact: The .NET SDK populates InnerFailure from InnerException. The JS SDK should match this behavior.

Proposed Fix

Recursively populate innerFailure from error.cause in newFailureDetails(), with a depth limit (10) to guard against pathological circular cause chains.

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