Skip to content

fix(error-tracking): install autocapture handler by default on first launch#650

Draft
ioannisj wants to merge 1 commit into
mainfrom
fix/error-tracking-first-launch-648
Draft

fix(error-tracking): install autocapture handler by default on first launch#650
ioannisj wants to merge 1 commit into
mainfrom
fix/error-tracking-first-launch-648

Conversation

@ioannisj

Copy link
Copy Markdown
Contributor

💡 Motivation and Context

Fixes #648.

On the very first app launch there's no disk-cached remote config yet, so the native crash handler (PostHogErrorTrackingAutoCaptureIntegration, a Thread.UncaughtExceptionHandler) didn't install until the async /flags remote-config response arrived. Any uncaught exception in that window, from app start to the first config response, was lost. Offline made it worse: a failed first-launch fetch left autocapture off for the whole session.

This flips the gate to match the iOS fix. The handler now installs by default at setup when local errorTrackingConfig.autoCapture is on, and only skips when a remote config that actually exists (fetched this session or disk-cached from a prior launch) explicitly reports autocaptureExceptions: false. Remote config becomes a kill-switch rather than a prerequisite: if the freshly-loaded config disables autocapture, onRemoteConfig uninstalls the handler, and a failed fetch leaves the default install in place. Local autoCapture stays the primary gate, so a host that turned it off still gets no handler.

To tell "first launch, no config yet" apart from "config exists and says disabled", PostHogRemoteConfig gains hasCachedErrorTrackingConfig(), set at startup when the error-tracking config was already on disk. It's the Android analogue of iOS's hasCachedRemoteConfig.

This is the Android counterpart of iOS #551, ported from iOS #731. It also covers Flutter-on-Android, which maps captureNativeExceptions onto errorTrackingConfig.autoCapture and inherited the same gap.

💚 How did you test it?

Unit tests mirroring the iOS installation tests, in PostHogErrorTrackingAutoCaptureIntegrationTest:

  • installs by default on first launch, before remote config arrives
  • does not install when local autoCapture is off, even with no remote config
  • does not install when a cached or fetched remote config disables autocapture
  • installs when a cached remote config enables autocapture
  • onRemoteConfig uninstalls the default install when a freshly-loaded config disables autocapture, and keeps it when the config enables autocapture
  • a failed fetch (loaded = false) keeps the default install

Ran ./gradlew spotlessApply, :posthog:apiCheck, and the full :posthog:test suite, all green.

📝 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

🤖 Agent context

DRI: @ioannisj
Autonomy: Human-driven (agent-assisted)

@ioannisj ioannisj self-assigned this Jul 22, 2026
@github-actions

Copy link
Copy Markdown
Contributor
⚠️ Possible changeset mismatch — 1 undeclared, 1 extra

This is informational — the PR is not blocked. Click the triangle above to collapse, or push a fix and this comment will auto-delete.

Modified in this PR but not in any changeset:

  • posthog

If this package should ship the change, add it to the changeset frontmatter:

---
"posthog": patch
---

Declared in a changeset but no source files modified:

  • posthog-android

Double-check this is intentional — for example, releasing a previously-merged change.

Changesets in this PR:

  • posthog-android — patch

@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

posthog-android Compliance Report

Date: 2026-07-24 07:02:06 UTC
Duration: 118356ms

✅ All Tests Passed!

46/46 tests passed


Capture Tests

29/29 tests passed

View Details
Test Status Duration
Format Validation.Event Has Required Fields 365ms
Format Validation.Event Has Uuid 36ms
Format Validation.Event Has Lib Properties 30ms
Format Validation.Distinct Id Is String 27ms
Format Validation.Token Is Present 25ms
Format Validation.Custom Properties Preserved 25ms
Format Validation.Event Has Timestamp 27ms
Retry Behavior.Retries On 503 7026ms
Retry Behavior.Does Not Retry On 400 4022ms
Retry Behavior.Does Not Retry On 401 4023ms
Retry Behavior.Respects Retry After Header 7027ms
Retry Behavior.Implements Backoff 17027ms
Retry Behavior.Retries On 500 7019ms
Retry Behavior.Retries On 502 7019ms
Retry Behavior.Retries On 504 7017ms
Retry Behavior.Max Retries Respected 17022ms
Deduplication.Generates Unique Uuids 36ms
Deduplication.Preserves Uuid On Retry 7015ms
Deduplication.Preserves Uuid And Timestamp On Retry 12033ms
Deduplication.Preserves Uuid And Timestamp On Batch Retry 7020ms
Deduplication.No Duplicate Events In Batch 38ms
Deduplication.Different Events Have Different Uuids 25ms
Compression.Sends Gzip When Enabled 20ms
Batch Format.Uses Proper Batch Structure 19ms
Batch Format.Flush With No Events Sends Nothing 14ms
Batch Format.Multiple Events Batched Together 33ms
Error Handling.Does Not Retry On 403 4023ms
Error Handling.Does Not Retry On 413 4021ms
Error Handling.Retries On 408 5029ms

Feature_Flags Tests

17/17 tests passed

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

@ioannisj
ioannisj force-pushed the fix/error-tracking-first-launch-648 branch from bf14bc3 to 81ce5d7 Compare July 24, 2026 06:56
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.

Bug: error tracking autocapture misses crashes on first launch before remote config resolves

1 participant