Skip to content

fix(amplitude-session): recover lastEventTime on partial persist#1198

Open
abueide wants to merge 2 commits intomasterfrom
fix/ios-zero-second-sessions
Open

fix(amplitude-session): recover lastEventTime on partial persist#1198
abueide wants to merge 2 commits intomasterfrom
fix/ios-zero-second-sessions

Conversation

@abueide
Copy link
Copy Markdown
Contributor

@abueide abueide commented Apr 7, 2026

Summary

Fixes 0-second sessions in the Amplitude Session plugin on iOS when Background Fetch is enabled.

Root cause: The plugin persists sessionId, lastEventTime, and eventSessionId to AsyncStorage via independent fire-and-forget writes in property setters. If the app is killed before all writes complete (common during iOS Background Fetch), sessionId may persist while lastEventTime does not. On the next launch, lastEventTime === -1 with a valid sessionId falsely triggers session expiration, ending the just-created session immediately — producing a 0-second session.

Fix: When lastEventTime === -1 but sessionId >= 0 (indicating partial persistence), recover lastEventTime from sessionId instead of treating the session as expired. Also removes the incorrect 1-second timestamp guard from onForeground() that was based on a disproven hypothesis.

Changes

  • startNewSessionIfNecessary(): Add recovery logic for partial AsyncStorage persistence
  • startNewSessionIfNecessary(): Remove lastEventTime === -1 from isSessionExpired (now handled by recovery)
  • onForeground(): Remove incorrect 1-second timestamp guard
  • Tests: Add 8 hypothesis-driven reproduction tests for 0-second sessions

Test plan

  • All 29 plugin tests pass
  • Full test suite (488 tests) passes
  • Hypothesis F test reproduces the bug on unpatched code, passes with fix
  • Hypothesis A test verifies lastEventTime recovery from sessionId
  • Manual test on iOS device with Background Fetch enabled

🤖 Generated with Claude Code

abueide and others added 2 commits April 7, 2026 11:25
… Fetch

iOS Background Fetch can briefly trigger AppState 'active' without user
interaction, causing rapid session creation/destruction cycles. Add a
1-second timestamp guard in onForeground() to prevent new sessions from
starting within 1 second of the last session creation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace incorrect 1-second timestamp guard with proper root cause fix.

The 0-second session bug is caused by non-atomic AsyncStorage persistence:
when the app is killed (e.g. during iOS Background Fetch), sessionId may
persist while lastEventTime does not. On relaunch, lastEventTime === -1
with a valid sessionId falsely triggers session expiration, ending the
just-created session immediately.

The fix recovers lastEventTime from sessionId when partial persistence
is detected, preventing the false expiration. Also adds hypothesis-driven
reproduction tests that verify the fix.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@abueide abueide changed the title fix(amplitude-session): prevent 0-second sessions from iOS Background Fetch fix(amplitude-session): recover lastEventTime on partial persist Apr 7, 2026
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.

1 participant