Skip to content

[copilot-finds] Bug: handleEntityOperationFailed discards EntityOperationFailedException, throwing generic TaskFailedError instead #227

@github-actions

Description

@github-actions

Problem

In packages/durabletask-js/src/worker/orchestration-executor.ts, the handleEntityOperationFailed method (line 566) creates an EntityOperationFailedException but immediately discards it, only extracting its .message property:

const exception = new EntityOperationFailedException(
  pendingCall.entityId,
  pendingCall.operationName,
  failureDetails,
);
pendingCall.task.fail(exception.message, failedEvent?.getFailuredetails());

CompletableTask.fail() always creates a new generic TaskFailedError, so the EntityOperationFailedException instance (with entity-specific context like entityId, operationName, and structured failureDetails) is lost.

Root Cause

CompletableTask.fail(message, details) unconditionally creates a TaskFailedError. There was no way to pass a pre-constructed exception to the task system, so the handler extracted only the .message string from the EntityOperationFailedException and discarded the rest.

Impact

  • API contract violation: The OrchestrationEntityFeature.callEntity() interface documents @throws {EntityOperationFailedException}, but users actually receive TaskFailedError.
  • Lost context: Entity-specific error information (entityId, operationName, structured failureDetails) is unavailable in catch blocks.
  • Dead code: The EntityOperationFailedException class is exported and has unit tests, but is never actually thrown to user code.

Severity: Medium — Affects all entity operation failure paths in orchestrations. Users relying on instanceof EntityOperationFailedException checks will never match.

Proposed Fix

  1. Make EntityOperationFailedException extend TaskFailedError (backward-compatible: existing instanceof TaskFailedError checks still work)
  2. Add failWithError() method to CompletableTask for pre-constructed exceptions
  3. Update handleEntityOperationFailed to use the EntityOperationFailedException directly

Metadata

Metadata

Assignees

No one assigned

    Labels

    copilot-findsFindings from daily automated code review agent

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions