Repository navigation
fix(otel): omit absent fields from error exception events - #901
Merged
Merged
Conversation
A checkpointed error that stores only a message or only a type gained an invented value for the other field. `Span.record_exception` derives `exception.type`, `exception.message` and `exception.stacktrace` from the carrier exception and only then merges the explicit attributes, so the plain `Exception` carrier supplied a type of `Exception`, an empty message and a synthetic stack trace that the explicit attributes could not delete. Emit the event with `add_event` directly from the checkpointed fields. The carrier exception and its default-message fallback are no longer needed, so both are removed.
This comment has been minimized.
This comment has been minimized.
zhongkechen
commented
Nov 2, 2026
hln33
reviewed
Nov 2, 2026
hln33
approved these changes
Nov 2, 2026
The OTel exception conventions make `exception.type` and `exception.message` each required when the other is absent, so an event carrying neither is malformed. Omitting both, as the previous commit did, traded one convention violation for another. Record no event in that case instead. Inventing a value is the defect this module exists to avoid, and the span's error status and `durable.operation.status` already report the failure. A stack trace alone does not satisfy the requirement, since `exception.stacktrace` is only recommended.
zhongkechen
force-pushed
the
issue-894-partial-error-events
branch
from
November 2, 2026 21:32
0b63e51 to
ad4e452
Compare
nvasiu
approved these changes
Nov 2, 2026
Contributor
Codex AI reviewTwo approach findings:
No SDK correctness regression confirmed. Tests were inspected but not executed, as requested. Reviewed commit |
6 of 21 tasks
3 tasks done
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #894
Problem
A callback or other operation that fails with only
ErrorMessageor onlyErrorTypeproduced an OTel exception event with an invented value for themissing field: a message-only error reported
exception.type = "Exception",and a type-only error reported an empty
exception.message. A syntheticexception.stacktracewas emitted too. Consumers could not distinguish absentmetadata from generated values.
exception_events.pybuilt a plainExceptioncarrier and calledSpan.record_exception, which derives attributes from the carrier beforemerging explicit attributes. Omitting a field from that explicit mapping cannot
remove the generated value. Core
ErrorObjectalready preserves absent fieldsas
None.Change
record_error_object_exceptionemits the event directly withspan.add_event("exception", attributes=..., timestamp=...), using the existingmapping of checkpointed fields. The carrier exception,
exception_from_error_object,and
_DEFAULT_MESSAGEfallback are removed.empty strings remain distinct from absent fields.
a stacktrace is present. The OTel exception conventions
require
exception.messageifexception.typeis unset, and vice versa;exception.stacktracealone does not satisfy that requirement. This guardavoids both malformed events and invented diagnostics. The span's error
status and
durable.operation.statusstill report the failure.exception.escapedand synthetic stacktraces from thecarrier. A stored, nonempty stacktrace is still included when an exception
event is emitted. Removing synthetic stacktraces also addresses that symptom
from [Bug]: Align OTel exception stacktrace emission with OpenTelemetry JS #886.
the README's status-mapping section.
Core checkpoint serialization,
CallbackExternalErrordiagnostics, and thenormalized event timestamp are unchanged. No conformance requirements or
handlers are changed.
Tests
tests/test_status_mapping.pychecks the exact exception attributes for fivepartial-field combinations: message-only, type-only, and three combinations
of explicit empty strings. These cover operation and failed-attempt recorders
in both views; failed-attempt cases also cover replayed and non-replayed
delivery. Exact attribute assertions exclude synthetic fields.
test_error_without_type_or_message_records_no_eventcovers 12 combinations:both views, operation and attempt recorders, and absent, empty, or nonempty
stacktraces. It asserts no exception events and retained span
ERRORstatus.tests/e2e/test_partial_callback_error_int.pyadds 12 callback cases throughDurableFunctionTestRunner,context.wait_for_callback, andsend_callback_failure. These cover message-only and type-only errors inboth views, same-invocation and post-resume completion, and caught and uncaught
failures. They check that the submitter step runs once, caught failures allow
handler success, and uncaught failures preserve the failure statuses.
The former message-only fallback test is replaced by the partial-field tests.
test_failed_operation_without_type_or_message_uses_fallbackis replaced bytest_error_without_type_or_message_records_no_event, which checks suppressionand retained error status. The carrier's fallback-message test is removed with
the function it tested.
Validation
At current head
ad4e452a25e0c51ece143cda0f8aba7cd711c1cd:hatch run dev-otel:python -m pytest packages/aws-durable-execution-sdk-python-otel/tests/test_status_mapping.py -q:198 passed on Python 3.13.18.
a2e9c7f2reproduced an emptyexception event for missing type/message with absent or empty stacktraces,
and a stacktrace-only event for a nonempty stacktrace. The current code emits
no event in all three cases.
Earlier validation reported passing callback e2e tests, formatting, linting,
and changed-file type checks. Its full OTel-suite run reported 12 failures in
tests/e2e/test_view_registration.py, also reproduced with the change reverted.Those broader checks were not rerun during the current-head validation above.
Validation is local; Lambda and X-Ray behavior has not been verified.