Skip to content

fix: Preserve original gRPC error cause in rewindInstance and restartOrchestration#200

Open
YunchuWang wants to merge 1 commit intomainfrom
copilot-finds/bug/preserve-grpc-error-cause-in-client
Open

fix: Preserve original gRPC error cause in rewindInstance and restartOrchestration#200
YunchuWang wants to merge 1 commit intomainfrom
copilot-finds/bug/preserve-grpc-error-cause-in-client

Conversation

@YunchuWang
Copy link
Member

Fixes #185

Problem

rewindInstance and restartOrchestration in TaskHubGrpcClient catch gRPC errors and rethrow new Error objects with user-friendly messages, but discard the original error. Users cannot access the original gRPC ServiceError details (metadata, status details, stack trace).

Changes

  • Add { cause: e } to all rethrown errors in both methods
  • Standardize rewindInstance gRPC error detection to use instanceof Error (consistent with restartOrchestration)
  • Consistent with existing error wrapping pattern used elsewhere in the codebase

…tion

The rewindInstance and restartOrchestration methods in TaskHubGrpcClient
catch gRPC errors and rethrow new Error objects with user-friendly
messages, but discard the original error. This loses valuable debugging
information (gRPC metadata, status details, and stack traces).

Changes:
- Add { cause: e } to all rethrown errors in rewindInstance, preserving
  the original gRPC ServiceError for debugging
- Add { cause: e } to all rethrown errors in restartOrchestration
- Standardize gRPC error detection in rewindInstance to use
  'instanceof Error' (consistent with restartOrchestration) instead of
  duck-typing with 'typeof e === "object"'
- Add comprehensive unit tests verifying error cause preservation for
  all handled gRPC status codes (NOT_FOUND, FAILED_PRECONDITION,
  UNIMPLEMENTED, CANCELLED) and passthrough of unrecognized errors

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 23, 2026 22:54
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes loss of diagnostic information in the DurableTask JS SDK client by preserving the original gRPC ServiceError as the cause when TaskHubGrpcClient.rewindInstance() and TaskHubGrpcClient.restartOrchestration() wrap errors, aligning with existing error-wrapping patterns in the repo.

Changes:

  • Preserve original caught gRPC errors via new Error(message, { cause: e }) in rewindInstance and restartOrchestration.
  • Standardize rewindInstance gRPC error detection to use e instanceof Error && "code" in e.
  • Add Jest coverage to validate cause preservation and wrapping behavior for key gRPC status codes.

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 1 comment.

File Description
packages/durabletask-js/src/client/client.ts Preserves original gRPC error as cause when rethrowing user-friendly errors in rewind/restart operations.
packages/durabletask-js/test/client-error-cause.spec.ts Adds tests ensuring wrapped errors preserve cause and unrecognized gRPC errors are rethrown unchanged.
package-lock.json Lockfile metadata update (removal of several "peer": true entries).

}
if (grpcError.code === grpc.status.CANCELLED) {
throw new Error(`The rewind operation for '${instanceId}' was cancelled.`);
throw new Error(`The rewind operation for '${instanceId}' was cancelled.`, { cause: e });
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this file, cancellation is spelled both as "canceled" (e.g., restartOrchestration/getOrchestrationHistory) and "cancelled" (rewindInstance). Since these are user-facing error messages, please standardize on a single spelling for consistency (and update the corresponding test expectation).

Suggested change
throw new Error(`The rewind operation for '${instanceId}' was cancelled.`, { cause: e });
throw new Error(`The rewind operation for '${instanceId}' was canceled.`, { cause: e });

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[copilot-finds] Bug: rewindInstance and restartOrchestration discard original gRPC error cause

2 participants