fix(errors): emit $exception_list in canonical order (caught-first, root cause last)#728
Draft
cat-ph wants to merge 2 commits into
Draft
fix(errors): emit $exception_list in canonical order (caught-first, root cause last)#728cat-ph wants to merge 2 commits into
cat-ph wants to merge 2 commits into
Conversation
$exception_list[0] is now the caught/outermost exception, with each cause appended after its wrapper in unwrap order and the root cause last. Previously the list was reversed so the root cause came first, which is the opposite of every other SDK. This aligns posthog-python with the cross-SDK exception ordering spec (PostHog/sdk-specs#11). Frame order within each stacktrace is unchanged (already bottom-up). Adds regression tests for explicit cause, implicit context, and ExceptionGroup ordering.
Contributor
|
Reviews (1): Last reviewed commit: "chore: use pypi/posthog changeset key" | Re-trigger Greptile |
Contributor
posthog-python Compliance ReportDate: 2026-07-03 00:25:55 UTC ✅ All Tests Passed!46/46 tests passed Capture Tests✅ 29/29 tests passed View Details
Feature_Flags Tests✅ 17/17 tests passed View Details
|
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.
Problem
posthog-python is the only SDK that emits
$exception_listwith the root cause first. Every other SDK with exception-chain support puts the caught/outermost exception at index0.exceptions_from_error_tuple()walked the chain in caught-first order and then called.reverse(), flipping it to root-cause-first.This is the Python side of the cross-SDK exception-ordering standardization: PostHog/sdk-specs#11.
Canonical order:
$exception_list[0]= the caught/outermost exception; each cause is appended after its wrapper in unwrap order; the root cause is last.Change
.reverse()inexceptions_from_error_tuple()(posthog/exception_utils.py). Both build paths already produce the list in canonical order:walk_exception_chainyields caught-first, following__cause__/__context__;ExceptionGroup:exceptions_from_errorkeeps the group (parent) before its contained exceptions.No code in the SDK or the Django integration derives values from
$exception_listpositions (e.g. no issue-name/type/message picking off[0]), so there is no downstream code change needed in this repo.Tests
Added regression tests in
posthog/test/test_exception_capture.py:raise B from A) -> asserts[0]is the caughtBand the last entry is root causeA;ExceptionGroup(3.11+) -> asserts the group is first, members follow.uv run pytest posthog/test/test_exception_capture.py posthog/test/test_client.py-> 145 passed (re-run after rebase onto current main). Ruff lint + format clean.Coordination
BREAKING wire-order change. The ordering of
$exception_liston the wire flips. Merge/release only after the pipeline normalization gate (cymbal) is live, so the pipeline can normalize incoming order based on$lib_version. Shipping this as a MINOR release (changeset included) so the pipeline can gate on the version. This flip should be paired with fingerprint aliasing on the pipeline side, since exception/frame fingerprints are order-sensitive.User-visible effects
Anything downstream that reads
$exception_list[0](issue fingerprinting / naming, primary exception type + message) will now see the caught/outermost exception instead of the root cause. That is the intended, canonical behavior and matches the other SDKs — but it is a visible change for existing Python-sourced issues.