Skip to content

Document errors across durable operation boundaries #253

Description

@yaythomas

Problem

The error-handling documentation does not explain what happens when an error crosses a durable operation boundary.

A durable operation failure does not propagate as the same in-memory exception object through one uninterrupted call stack. The SDK serializes the failure into a durable error record at the operation boundary. A receiving operation may reconstruct that record later, in another invocation or process.

Without this explanation, customers can reasonably expect the original exception class, custom properties, stack trace, and complete cause graph to arrive unchanged at an outer operation.

Proposed documentation

Add a section to the shared Error handling page.

Errors across operation boundaries

Durable operations checkpoint failures so executions can replay after process termination, migration, or interruption. When an error crosses a durable operation boundary, the SDK:

  1. Converts the error into a durable representation containing fields such as error type, message, structured error data, and stack trace.
  2. Stores that representation in the execution history.
  3. Reconstructs an error for the receiving operation when execution resumes.

The reconstructed error is not necessarily the original in-memory exception object. Applications should not assume that the following remain unchanged across durable operation boundaries:

  • the original exception class;
  • custom exception properties;
  • the exact cause or exception graph;
  • object identity;
  • the original runtime stack trace.

The receiving SDK provides an operation-level error that describes where the durable failure occurred. Structured application details should be placed in the durable error-data field.

If application code must make business decisions from a failure, catch it at the operation that owns the decision and return a typed domain outcome. For example:

{
  "ok": false,
  "reason": {
    "kind": "payment_rejected",
    "code": "CARD_DECLINED",
    "retryable": false
  }
}

Throw an error when the durable operation or execution itself must remain failed. Use structured error data to retain details needed for diagnostics or external consumers.

SDK-specific reconstruction

Error reconstruction differs by SDK and language runtime:

  • JavaScript: Reconstructs SDK operation-error wrappers. Application exception classes and custom properties do not propagate through multiple durable boundaries. Structured errorData remains available, although it may be attached to a nested cause rather than the outer wrapper.
  • Python: Reconstructs registered SDK operation-error classes. Unknown error types fall back to DurableOperationError.
  • Java: Serializes the throwable into error data and attempts to reconstruct the throwable class. This behavior depends on the class being available and deserializable.

Applications should therefore rely on documented durable fields rather than assuming equivalent exception-object reconstruction across SDKs.

Acceptance criteria

  • The shared error-handling page defines a durable operation boundary.
  • The page explains that errors are serialized, checkpointed, and reconstructed.
  • The page distinguishes durable error propagation from ordinary in-process exception propagation.
  • The page identifies which error characteristics applications must not assume remain intact.
  • The page recommends structured domain outcomes for business decisions.
  • The page includes language-specific reconstruction notes for JavaScript, Python, and Java.
  • Individual operation pages can link to this shared explanation rather than repeating it.
  • document best practice around using errorData for custom data

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentation

    Type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions