Skip to content

Add custom FailureDetails properties - #253

Open
andystaples wants to merge 6 commits into
mainfrom
andystaples-failure-details-properties
Open

Add custom FailureDetails properties#253
andystaples wants to merge 6 commits into
mainfrom
andystaples-failure-details-properties

Conversation

@andystaples

@andystaples andystaples commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add ExceptionPropertiesProvider and worker configuration for portable exception metadata.
  • Preserve recursive failure details and custom properties across task exceptions, orchestration state, history, and entity failures.
  • Document supported values and the intentional dt: / dto: .NET parity gap; add core and Azure Managed changelog entries.

Validation

  • python -m pytest tests\durabletask\test_failure_details.py tests\durabletask\entities\test_entity_failure_handling.py
  • python -m pytest tests\durabletask-azuremanaged\test_azuremanaged_grpc_resiliency.py
  • python -m flake8 durabletask
  • python -m flake8 tests\durabletask
  • python -m flake8 durabletask-azuremanaged
  • python -m flake8 tests\durabletask-azuremanaged
  • python -m pyright on changed production files
  • python -m pymarkdown -c .pymarkdown.json scan README.md

Resolves #67

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 26daf565-a1f4-4bf0-9540-b57f31a4a12b
Copilot AI lite review requested due to automatic review settings August 10, 2026 16:38
Comment thread durabletask/worker.py Fixed
Comment thread tests/durabletask/entities/test_entity_failure_handling.py Fixed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 extends the Durable Task Python SDK to support portable, custom exception metadata by introducing an ExceptionPropertiesProvider and plumbing its output into FailureDetails so properties (and inner failures) round-trip through task exceptions, orchestration state, history, and entity failures.

Changes:

  • Added ExceptionPropertiesProvider (worker option) and propagated it through worker execution paths to enrich protobuf TaskFailureDetails.
  • Extended the public FailureDetails model (inner failures + properties) and updated parsing in client/history/task failure surfaces.
  • Added tests, README documentation, and changelog entries for core + Azure Managed packages.

Reviewed changes

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

Show a summary per file
File Description
tests/durabletask/test_failure_details.py Adds unit tests validating property serialization, inner-failure preservation, and provider failure behavior.
tests/durabletask/entities/test_entity_failure_handling.py Adds an E2E entity test ensuring exception properties are observable by orchestrators.
tests/durabletask-azuremanaged/test_azuremanaged_grpc_resiliency.py Verifies Azure Managed worker forwards the provider to the base worker.
README.md Documents feature usage, supported value shapes, and .NET dt:/dto: parity gap.
durabletask/worker.py Introduces the provider Protocol and threads it through orchestration/activity/entity failure reporting.
durabletask/task.py Extends FailureDetails and ensures TaskFailedError.details uses the shared protobuf-to-model conversion.
durabletask/internal/helpers.py Implements protobuf<->Python value conversion plus failure-details property extraction.
durabletask/history.py Switches history failure-details parsing to the shared protobuf converter (to include properties/inner failures).
durabletask/client.py Switches orchestration-state failure-details parsing to the shared protobuf converter.
durabletask/init.py Exposes ExceptionPropertiesProvider from the package root.
durabletask-azuremanaged/durabletask/azuremanaged/worker.py Adds exception_properties_provider to DurableTaskSchedulerWorker and forwards it to the base worker.
durabletask-azuremanaged/CHANGELOG.md Adds Unreleased entry documenting the new worker option.
CHANGELOG.md Adds Unreleased entry documenting the new provider and failure-details enrichment.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread durabletask/internal/helpers.py
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 26daf565-a1f4-4bf0-9540-b57f31a4a12b
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 26daf565-a1f4-4bf0-9540-b57f31a4a12b
Comment thread durabletask/exception_properties.py Dismissed
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 26daf565-a1f4-4bf0-9540-b57f31a4a12b

@berndverst Bernd Verst (berndverst) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Requesting changes because an unhandled failed task drops its original custom properties and inner-failure chain when it fails the parent orchestration. Core history-export state metadata also omits the new fields.

Comment thread durabletask/worker.py Outdated
pb.ORCHESTRATION_STATUS_FAILED,
None,
ph.new_failure_details(ex) if isinstance(ex, Exception) else ex,
ph.new_failure_details(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Unhandled task failures lose the metadata this PR just captured. When an activity, entity, or sub-orchestration failure escapes the orchestrator, ex is a TaskFailedError; rebuilding it here serializes only that wrapper and calls the provider on TaskFailedError, while its existing details (the original properties and inner chain) are discarded. With a provider that returns {"code": "VALUE"} only for ValueError, the activity failure has the property, but the final OrchestrationState.failure_details has properties=None and inner_failure=None. Please carry the underlying task failure into the orchestration failure (for example as its inner failure) and add an unhandled-task regression test.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in ddaa948. Unhandled TaskFailedError instances now retain the original protobuf TaskFailureDetails as the orchestration failure's inner failure, preserving custom properties and the complete existing inner-failure chain. Added a regression test.

Comment thread durabletask/task.py
error_type: str
stack_trace: str | None
inner_failure: FailureDetails | None = None
properties: dict[str, Any] | None = None

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

One core serialization path still drops these fields: durabletask.extensions.history_export.serialization.orchestration_state_to_dict() manually emits only message/type/stack and one inner level, so exported state metadata omits properties and truncates deeper causes, while failure-bearing history events include them. Please use a shared recursive FailureDetails serializer there and cover state metadata with properties plus a multi-level inner chain.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in ddaa948. History export now uses a recursive FailureDetails serializer for orchestration-state metadata, including properties and every inner-failure level. Added multi-level coverage.

andystaples and others added 2 commits August 13, 2026 10:48
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 26daf565-a1f4-4bf0-9540-b57f31a4a12b
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.

Add support for custom properties in FailureDetails

3 participants