Skip to content

fix: attach map_id to frames from stateless exception capture - #668

Merged
cat-ph merged 3 commits into
mainfrom
fix/stateless-exception-map-id
Aug 5, 2026
Merged

fix: attach map_id to frames from stateless exception capture#668
cat-ph merged 3 commits into
mainfrom
fix/stateless-exception-map-id

Conversation

@cat-ph

@cat-ph cat-ph commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

💡 Motivation and Context

captureExceptionStateless did not pass config.releaseIdentifier to ThrowableCoercer, so exceptions captured through the stateless path never got map_id on their stack frames and could not be symbolicated against uploaded ProGuard/R8 mappings. The stateful captureException path already threads it through correctly.

This also affected posthog-server, whose captureException delegates to the stateless path — and additionally the server PostHogConfig had no way to set a releaseIdentifier at all (asCoreConfig() never assigned one).

Changes:

  • Pass config.releaseIdentifier to ThrowableCoercer in captureExceptionStateless, matching the stateful path.
  • Expose releaseIdentifier on posthog-server's PostHogConfig (property + builder method) and propagate it in asCoreConfig().

💚 How did you test it?

  • New regression test in PostHogStatelessTest asserting map_id appears on every frame when releaseIdentifier is set.
  • New end-to-end test in posthog-server's PostHogTest asserting frames captured via the server captureException carry map_id.
  • New PostHogConfigTest cases for asCoreConfig() propagation and the builder method.
  • make test, make checkFormat, and apiCheck pass; apiDump regenerated for the new server API.

📝 Checklist

  • I reviewed the submitted code.
  • I added tests to verify the changes.
  • I updated the docs if needed.
  • No breaking change or entry added to the changelog.

If releasing new changes

  • Ran pnpm changeset to generate a changeset file

cat-ph added 2 commits August 1, 2026 01:22
captureExceptionStateless did not pass config.releaseIdentifier to
ThrowableCoercer, so exceptions captured via the stateless path
(including posthog-server's captureException) had no map_id on their
stack frames and could not be symbolicated against uploaded ProGuard
mappings. Thread releaseIdentifier through like the stateful
captureException path does.
The core stateless fix alone did not help posthog-server users: the
server config had no releaseIdentifier and asCoreConfig() never set
one, so server captureException calls still emitted frames without
map_id. Expose the setting (property + builder method), propagate it
in asCoreConfig(), and add an end-to-end regression test asserting
map_id on frames captured through the server API.
@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

posthog-android Compliance Report

Date: 2026-08-03 22:29:59 UTC
Duration: 118331ms

✅ All Tests Passed!

46/46 tests passed


Capture Tests

29/29 tests passed

View Details
Test Status Duration
Format Validation.Event Has Required Fields 356ms
Format Validation.Event Has Uuid 36ms
Format Validation.Event Has Lib Properties 31ms
Format Validation.Distinct Id Is String 27ms
Format Validation.Token Is Present 26ms
Format Validation.Custom Properties Preserved 22ms
Format Validation.Event Has Timestamp 26ms
Retry Behavior.Retries On 503 7029ms
Retry Behavior.Does Not Retry On 400 4026ms
Retry Behavior.Does Not Retry On 401 4024ms
Retry Behavior.Respects Retry After Header 7027ms
Retry Behavior.Implements Backoff 17034ms
Retry Behavior.Retries On 500 7019ms
Retry Behavior.Retries On 502 7017ms
Retry Behavior.Retries On 504 7018ms
Retry Behavior.Max Retries Respected 17021ms
Deduplication.Generates Unique Uuids 37ms
Deduplication.Preserves Uuid On Retry 7014ms
Deduplication.Preserves Uuid And Timestamp On Retry 12023ms
Deduplication.Preserves Uuid And Timestamp On Batch Retry 7020ms
Deduplication.No Duplicate Events In Batch 35ms
Deduplication.Different Events Have Different Uuids 23ms
Compression.Sends Gzip When Enabled 21ms
Batch Format.Uses Proper Batch Structure 18ms
Batch Format.Flush With No Events Sends Nothing 25ms
Batch Format.Multiple Events Batched Together 40ms
Error Handling.Does Not Retry On 403 4021ms
Error Handling.Does Not Retry On 413 4021ms
Error Handling.Retries On 408 5028ms

Feature_Flags Tests

17/17 tests passed

View Details
Test Status Duration
Request Payload.Request With Person Properties Device Id 31ms
Request Payload.Flags Request Uses V2 Query Param 21ms
Request Payload.Flags Request Hits Flags Path Not Decide 21ms
Request Payload.Flags Request Omits Authorization Header 24ms
Request Payload.Token In Flags Body Matches Init 22ms
Request Payload.Groups Round Trip 22ms
Request Payload.Groups Default To Empty Object 25ms
Request Payload.Disable Geoip False Propagates As Geoip Disable False 21ms
Request Payload.Disable Geoip Omitted Defaults To False 19ms
Request Payload.Flag Keys To Evaluate Contains Only Requested Key 20ms
Request Lifecycle.No Flags Request On Init Alone 12ms
Request Lifecycle.No Flags Request On Normal Capture 28ms
Request Lifecycle.Two Flag Calls Produce Two Remote Requests 45ms
Request Lifecycle.Mock Response Value Is Returned To Caller 22ms
Retry Behavior.Retries Flags On 502 323ms
Retry Behavior.Retries Flags On 504 321ms
Side Effect Events.Get Feature Flag Captures Feature Flag Called Event 22ms

@cat-ph
cat-ph marked this pull request as ready for review August 3, 2026 22:23
@cat-ph
cat-ph requested a review from a team as a code owner August 3, 2026 22:23
@cat-ph
cat-ph requested review from a team, ablaszkiewicz and hpouillot August 3, 2026 22:23
@greptile-apps

greptile-apps Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Reviews (1): Last reviewed commit: "feat(server): expose releaseIdentifier o..." | Re-trigger Greptile

@ablaszkiewicz ablaszkiewicz 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.

🚢

Comment on lines +170 to +177
/**
* Identifier attached as `map_id` to exception stack frames so PostHog can symbolicate
* them against an uploaded ProGuard/R8 mapping. It must match the map-id used when
* uploading the mapping, e.g. via
* `posthog-cli exp proguard upload --path "mapping.txt" --map-id "<releaseIdentifier>"`.
* Defaults to null (no `map_id` attached).
*/
public var releaseIdentifier: String? = null

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.

not sure we need this in the server package, proguard/r8 are mainly android tools
you can minify server bundles with proguard but its not a common thing since the bundle lives in the server and its not exposed for reverse engineering

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.

hmm @marandaneto I was thinking that it's just general JVM SDK, so it can get shipped in desktop apps, CLI tools etc

it should technically be ~negligible cost here to pass the map_id (since captureException already does it too), but also related that I was looking into bringing more of the ET mechanism in "core" so we can expose it directly here too (i.e. #669 #670 and some upcoming draft ones I was testing/working on [extracted this one from #670 tbh]) 😁

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.

yeah its not a problem, but I doubt it'd be used

@cat-ph
cat-ph merged commit a890a02 into main Aug 5, 2026
16 checks passed
@cat-ph
cat-ph deleted the fix/stateless-exception-map-id branch August 5, 2026 11:16
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.

4 participants