Skip to content

fix(replay): follow session rotation while _isIdle is unknown - #4750

Open
sortafreel wants to merge 4 commits into
main-7c00f925from
fix/replay-session-rotation-while-idle-unknown
Open

fix(replay): follow session rotation while _isIdle is unknown#4750
sortafreel wants to merge 4 commits into
main-7c00f925from
fix/replay-session-rotation-while-idle-unknown

Conversation

@sortafreel

Copy link
Copy Markdown

Problem

Fixes #4202.

In a tab with no user interaction, the session recorder sits in the 'unknown' idle state (_isIdle: boolean | 'unknown'). Several guards treat that truthy string as "idle", so when the analytics session rotates via activity timeout (e.g. a long-lived background tab capturing an event), the recorder:

  • never restarts — _onSessionIdCallback only restarted when _isIdle === true, and _updateWindowAndSessionIds (the "otherwise" restart path its comment relies on) bailed early on truthy _isIdle
  • keeps stamping every event, including periodic full snapshots, with the old session id
  • never schedules a buffer flush, so data accumulates unbounded and ships nothing

Net effect, exactly as reported in #4202: the new session's only ingested blob is the $session_starting lifecycle event, there is no FullSnapshot under the new session id, and the replay is unplayable while get_session_replay_url() happily points at it.

Changes

Four one-line guard fixes in lazy-loaded-session-recorder.ts, all the same 'unknown'-truthiness family:

  1. _onSessionIdCallback restarts the recorder when _isIdle !== false (was === true), so a rotation in the 'unknown' state restarts immediately and the new session gets its own FullSnapshot.
  2. _updateWindowAndSessionIds bails only on confirmed idle (=== true), so a recorder in 'unknown' keeps checking for session changes on every event and self-heals a stale _sessionId. This revives the approach from fix(replay): detect session rotation while _isIdle is unknown #3511, which was approved but closed unmerged.
  3. The flush timer in _captureSnapshotBuffered is scheduled while 'unknown', so a no-interaction tab ships its buffer (including the post-rotation FullSnapshot) on the normal 2s cadence instead of holding it until the next rotation or unload. $snapshot capture returns before the session check in _calculate_event_properties, so flushing cannot extend the session, and _flushBuffer's own gating (buffering/paused/minimum duration) still applies.
  4. The buffer size cap likewise applies during 'unknown', so the buffer can no longer grow unbounded in memory.
  5. The restart guard in _onSessionIdCallback also requires the ids to still be stale: with real rrweb, the $session_id_change custom event is delivered synchronously through emit and re-enters _updateWindowAndSessionIds, which (after change 2) adopts the new ids and restarts the recorder itself — without the staleness check, every rotation in the 'unknown' state restarted twice, shipping two full DOM serializations. A rotation now restarts the recorder exactly once, and degraded paths (queued emit, blocked URL, stopped recorder) still fall back to the callback restart.

Capture (onRRwebEmit) and periodic snapshot scheduling already treated only === true as idle; this brings the remaining guards in line.

Test changes:

  • Unit regression tests for the bootup-'unknown' rotation, the reported two-rotation background-tab sequence, the stale-session-id re-sync, and the 'unknown'-state flush (red on the old code, green now).
  • A real-rrweb Playwright spec (both compression modes): rotation with zero user interaction must ship exactly one Meta + FullSnapshot pair under the new session id with no further activity. Verified failing against the unfixed bundle and passing with the fix.
  • A re-entrancy unit test with addCustomEvent forwarded into emit the way real rrweb delivers it, pinning the exactly-one-restart behavior of change 5 (red before that change, green after), plus a size-cap-while-'unknown' test for change 4.
  • Six existing tests re-staged: three session-linking tests now confirm user activity first (they implicitly relied on no-restart-during-'unknown'), and three fix(replay): attribute post-rotation snapshots to the new session while idle #4104 compression tests staged rotation by writing _sessionId without telling the session manager — a divergence the recorder now corrects — so they stage the manager too.

Release info Sub-libraries affected

Libraries affected

  • All of them
  • posthog-js (web)
  • posthog-js-lite (web lite)
  • posthog-node
  • posthog-react-native
  • @posthog/react-native-plugin
  • @posthog/react
  • @posthog/ai
  • @posthog/convex
  • @posthog/next
  • @posthog/nextjs-config
  • @posthog/nuxt
  • @posthog/openfeature-node-provider
  • @posthog/openfeature-web-provider
  • @posthog/rollup-plugin
  • @posthog/webpack-plugin
  • @posthog/types
  • @posthog/browser-common

Checklist

  • Tests for new code
  • Accounted for the impact of any changes across different platforms
  • Accounted for backwards compatibility of any changes (no breaking changes!)
  • Took care not to unnecessarily increase the bundle size

If releasing new changes

  • Ran pnpm changeset to generate a changeset file

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

  • Written with Claude Code. Investigation started from the Replay full snapshot remains on previous session after idle rotation in 1.404.1 #4202 report: reproduced the failure in unit tests against the real SessionIdManager → recorder callback chain before touching any code, then verified the fix end-to-end by rebuilding the bundle with and without the change and running the new Playwright spec against both (fails on the old bundle with exactly the reported symptom — only the $session_starting blob ships for the new session).
  • Considered fixing only the missed restart, but that leaves the new session's snapshot sitting in an unflushed buffer for up to the next rotation/unload (the reporter's "flushed size stayed 0 for over an hour"), so the flush guards were included; verified $snapshot capture cannot extend the session before making flushing more eager.

A recorder that has seen no user interaction stays in the 'unknown' idle state, where truthy _isIdle guards skipped rotation restarts, session-id re-sync, and buffer flushing, leaving new sessions without a playable full snapshot (#4202).
…action

Real-rrweb Playwright coverage for #4202: after an activity-timeout rotation in a tab with no interaction, the new session must ship Meta + FullSnapshot with no further activity.
…heck

The $session_id_change custom event synchronously re-enters _updateWindowAndSessionIds via rrweb's emit, which already adopts the ids and restarts; the callback now restarts only when the ids are still stale.
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

@greptile-apps

greptile-apps Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Reviews (1): Last reviewed commit: "fix(replay): restart only once when rota..." | Re-trigger Greptile

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Size Change: +186 B (0%)

Total Size: 17.8 MB

Filename Size Change
packages/browser/dist/array.full.no-********.js 532 kB +54 B (+0.01%)
packages/browser/dist/lazy-********.js 166 kB +39 B (+0.02%)
packages/browser/dist/module.full.no-********.js 535 kB +54 B (+0.01%)
packages/browser/dist/posthog-********.js 166 kB +39 B (+0.02%)
ℹ️ View Unchanged
Filename Size Change
packages/ai/dist/anthropic/index.cjs 28.2 kB 0 B
packages/ai/dist/anthropic/index.mjs 27.9 kB 0 B
packages/ai/dist/gemini/index.cjs 36.5 kB 0 B
packages/ai/dist/gemini/index.mjs 36.3 kB 0 B
packages/ai/dist/index.cjs 56.5 kB 0 B
packages/ai/dist/index.mjs 56.4 kB 0 B
packages/ai/dist/langchain/index.cjs 34.7 kB 0 B
packages/ai/dist/langchain/index.mjs 34.7 kB 0 B
packages/ai/dist/openai-agents/index.cjs 29.5 kB 0 B
packages/ai/dist/openai-agents/index.mjs 29.4 kB 0 B
packages/ai/dist/openai/index.cjs 81.2 kB 0 B
packages/ai/dist/openai/index.mjs 80.8 kB 0 B
packages/ai/dist/otel/index.cjs 17.2 kB 0 B
packages/ai/dist/otel/index.mjs 17.1 kB 0 B
packages/ai/dist/vercel/index.cjs 47.3 kB 0 B
packages/ai/dist/vercel/index.mjs 47.3 kB 0 B
packages/browser-common/dist/client.js 603 B 0 B
packages/browser-common/dist/client.mjs 0 B 0 B 🆕
packages/browser-common/dist/config.js 1.43 kB 0 B
packages/browser-common/dist/config.mjs 223 B 0 B
packages/browser-common/dist/constants.js 1.66 kB 0 B
packages/browser-common/dist/constants.mjs 219 B 0 B
packages/browser-common/dist/disposable.js 603 B 0 B
packages/browser-common/dist/disposable.mjs 0 B 0 B 🆕
packages/browser-common/dist/extension.js 603 B 0 B
packages/browser-common/dist/extension.mjs 0 B 0 B 🆕
packages/browser-common/dist/index.js 1.3 kB 0 B
packages/browser-common/dist/index.mjs 64 B 0 B
packages/browser-common/dist/persistence.js 603 B 0 B
packages/browser-common/dist/persistence.mjs 0 B 0 B 🆕
packages/browser-common/dist/pubsub.js 2.21 kB 0 B
packages/browser-common/dist/pubsub.mjs 1.03 kB 0 B
packages/browser-common/dist/token.js 603 B 0 B
packages/browser-common/dist/token.mjs 0 B 0 B 🆕
packages/browser-common/dist/utils/array-at-********.js 628 B 0 B
packages/browser-common/dist/utils/array-at-********.mjs 425 B 0 B
packages/browser-common/dist/utils/autocapture-utils.js 22.2 kB 0 B
packages/browser-common/dist/utils/autocapture-utils.mjs 16.6 kB 0 B
packages/browser-common/dist/utils/blocked-uas.js 2.1 kB 0 B
packages/browser-common/dist/utils/blocked-uas.mjs 598 B 0 B
packages/browser-common/dist/utils/cookie-utils.js 1.89 kB 0 B
packages/browser-common/dist/utils/cookie-utils.mjs 673 B 0 B
packages/browser-common/dist/utils/device-model-utils.js 1.98 kB 0 B
packages/browser-common/dist/utils/device-model-utils.mjs 678 B 0 B
packages/browser-common/dist/utils/element-utils.js 2.46 kB 0 B
packages/browser-common/dist/utils/element-utils.mjs 804 B 0 B
packages/browser-common/dist/utils/elements-chain-utils.js 2.77 kB 0 B
packages/browser-common/dist/utils/elements-chain-utils.mjs 1.23 kB 0 B
packages/browser-common/dist/utils/encode-utils.js 1.4 kB 0 B
packages/browser-common/dist/utils/encode-utils.mjs 205 B 0 B
packages/browser-common/dist/utils/event-utils.js 15.7 kB 0 B
packages/browser-common/dist/utils/event-utils.mjs 10 kB 0 B
packages/browser-common/dist/utils/general-utils.js 7.31 kB 0 B
packages/browser-common/dist/utils/general-utils.mjs 4.49 kB 0 B
packages/browser-common/dist/utils/globals.js 2.78 kB 0 B
packages/browser-common/dist/utils/globals.mjs 860 B 0 B
packages/browser-common/dist/utils/logger.js 3.4 kB 0 B
packages/browser-common/dist/utils/logger.mjs 1.61 kB 0 B
packages/browser-common/dist/utils/matcher-utils.js 2.85 kB 0 B
packages/browser-common/dist/utils/matcher-utils.mjs 1.33 kB 0 B
packages/browser-common/dist/utils/property-utils.js 5.38 kB 0 B
packages/browser-common/dist/utils/property-utils.mjs 3.34 kB 0 B
packages/browser-common/dist/utils/prototype-utils.js 3.03 kB 0 B
packages/browser-common/dist/utils/prototype-utils.mjs 1.4 kB 0 B
packages/browser-common/dist/utils/regex-utils.js 1.68 kB 0 B
packages/browser-common/dist/utils/regex-utils.mjs 378 B 0 B
packages/browser-common/dist/utils/request-utils.js 6.73 kB 0 B
packages/browser-common/dist/utils/request-utils.mjs 4.19 kB 0 B
packages/browser-common/dist/utils/simple-event-emitter.js 1.76 kB 0 B
packages/browser-common/dist/utils/simple-event-emitter.mjs 553 B 0 B
packages/browser-common/dist/utils/stylesheet-loader.js 2.13 kB 0 B
packages/browser-common/dist/utils/stylesheet-loader.mjs 823 B 0 B
packages/browser-common/dist/utils/type-utils.js 1.59 kB 0 B
packages/browser-common/dist/utils/type-utils.mjs 267 B 0 B
packages/browser-common/dist/utils/url-targeting-utils.js 2.35 kB 0 B
packages/browser-common/dist/utils/url-targeting-utils.mjs 863 B 0 B
packages/browser-common/dist/utils/uuidv7.js 6.66 kB 0 B
packages/browser-common/dist/utils/uuidv7.mjs 5.18 kB 0 B
packages/browser/dist/all-external-dependencies.js 243 kB 0 B
packages/browser/dist/array.full.es5.js 418 kB 0 B
packages/browser/dist/array.full.js 449 kB 0 B
packages/browser/dist/array.js 230 kB 0 B
packages/browser/dist/array.no-********.js 255 kB 0 B
packages/browser/dist/conversations.js 68.6 kB 0 B
packages/browser/dist/crisp-chat-integration.js 2.03 kB 0 B
packages/browser/dist/customizations.full.js 16 kB 0 B
packages/browser/dist/customizations.js 15.9 kB 0 B
packages/browser/dist/dead-clicks-autocapture.js 17 kB 0 B
packages/browser/dist/default-extensions.js 229 kB 0 B
packages/browser/dist/element-inference.js 5.62 kB 0 B
packages/browser/dist/exception-autocapture.js 11.9 kB 0 B
packages/browser/dist/extension-bundles.js 130 kB 0 B
packages/browser/dist/external-scripts-loader.js 3.16 kB 0 B
packages/browser/dist/intercom-integration.js 2.08 kB 0 B
packages/browser/dist/logs.js 4.41 kB 0 B
packages/browser/dist/main.js 235 kB 0 B
packages/browser/dist/module.full.js 452 kB 0 B
packages/browser/dist/module.js 234 kB 0 B
packages/browser/dist/module.no-********.js 259 kB 0 B
packages/browser/dist/module.slim.js 115 kB 0 B
packages/browser/dist/module.slim.no-********.js 122 kB 0 B
packages/browser/dist/product-tours-preview.js 76.7 kB 0 B
packages/browser/dist/product-tours.js 117 kB 0 B
packages/browser/dist/recorder-v2.js 109 kB 0 B
packages/browser/dist/recorder.js 109 kB 0 B
packages/browser/dist/rrweb-plugin-console-record.js 6.99 kB 0 B
packages/browser/dist/rrweb-types.js 2.33 kB 0 B
packages/browser/dist/rrweb.js 292 kB 0 B
packages/browser/dist/surveys-preview.js 78.5 kB 0 B
packages/browser/dist/surveys.js 97.6 kB 0 B
packages/browser/dist/tracing-headers.js 3.71 kB 0 B
packages/browser/dist/web-vitals-with-attribution.js 12.3 kB 0 B
packages/browser/dist/web-vitals.js 6.72 kB 0 B
packages/browser/react/dist/esm/index.js 21.1 kB 0 B
packages/browser/react/dist/esm/slim/index.js 17.5 kB 0 B
packages/browser/react/dist/esm/surveys/index.js 4.68 kB 0 B
packages/browser/react/dist/umd/index.js 24.4 kB 0 B
packages/browser/react/dist/umd/slim/index.js 20.3 kB 0 B
packages/browser/react/dist/umd/surveys/index.js 5.45 kB 0 B
packages/convex/dist/client/feature-flags/crypto.js 461 B 0 B
packages/convex/dist/client/feature-flags/evaluator.js 16.5 kB 0 B
packages/convex/dist/client/feature-flags/index.js 196 B 0 B
packages/convex/dist/client/feature-flags/match-********.js 14.8 kB 0 B
packages/convex/dist/client/feature-flags/types.js 44 B 0 B
packages/convex/dist/client/index.js 14.6 kB 0 B
packages/convex/dist/component/_generated/api.js 712 B 0 B
packages/convex/dist/component/_generated/component.js 212 B 0 B
packages/convex/dist/component/_generated/dataModel.js 230 B 0 B
packages/convex/dist/component/_generated/server.js 3.74 kB 0 B
packages/convex/dist/component/convex.config.js 1.66 kB 0 B
packages/convex/dist/component/crons.js 969 B 0 B
packages/convex/dist/component/lib.js 24.7 kB 0 B
packages/convex/dist/component/schema.js 1.17 kB 0 B
packages/convex/dist/component/version.js 68 B 0 B
packages/core/dist/cookie.js 5.34 kB 0 B
packages/core/dist/cookie.mjs 3.12 kB 0 B
packages/core/dist/error-tracking/chunk-ids.js 2.54 kB 0 B
packages/core/dist/error-tracking/chunk-ids.mjs 1.31 kB 0 B
packages/core/dist/error-tracking/coercers/dom-exception-coercer.js 2.3 kB 0 B
packages/core/dist/error-tracking/coercers/dom-exception-coercer.mjs 993 B 0 B
packages/core/dist/error-tracking/coercers/error-coercer.js 2.02 kB 0 B
packages/core/dist/error-tracking/coercers/error-coercer.mjs 794 B 0 B
packages/core/dist/error-tracking/coercers/error-event-coercer.js 1.76 kB 0 B
packages/core/dist/error-tracking/coercers/error-event-coercer.mjs 513 B 0 B
packages/core/dist/error-tracking/coercers/event-coercer.js 1.82 kB 0 B
packages/core/dist/error-tracking/coercers/event-coercer.mjs 548 B 0 B
packages/core/dist/error-tracking/coercers/index.js 6.79 kB 0 B
packages/core/dist/error-tracking/coercers/index.mjs 326 B 0 B
packages/core/dist/error-tracking/coercers/object-coercer.js 3.46 kB 0 B
packages/core/dist/error-tracking/coercers/object-coercer.mjs 2.07 kB 0 B
packages/core/dist/error-tracking/coercers/primitive-coercer.js 1.67 kB 0 B
packages/core/dist/error-tracking/coercers/primitive-coercer.mjs 419 B 0 B
packages/core/dist/error-tracking/coercers/promise-rejection-event.js 2.59 kB 0 B
packages/core/dist/error-tracking/coercers/promise-rejection-event.mjs 1.25 kB 0 B
packages/core/dist/error-tracking/coercers/string-coercer.js 2.01 kB 0 B
packages/core/dist/error-tracking/coercers/string-coercer.mjs 820 B 0 B
packages/core/dist/error-tracking/coercers/utils.js 2.06 kB 0 B
packages/core/dist/error-tracking/coercers/utils.mjs 716 B 0 B
packages/core/dist/error-tracking/error-properties-builder.js 5.56 kB 0 B
packages/core/dist/error-tracking/error-properties-builder.mjs 4.23 kB 0 B
packages/core/dist/error-tracking/exception-steps.js 6.01 kB 0 B
packages/core/dist/error-tracking/exception-steps.mjs 3.84 kB 0 B
packages/core/dist/error-tracking/index.js 4.74 kB 0 B
packages/core/dist/error-tracking/index.mjs 191 B 0 B
packages/core/dist/error-tracking/parsers/base.js 1.83 kB 0 B
packages/core/dist/error-tracking/parsers/base.mjs 464 B 0 B
packages/core/dist/error-tracking/parsers/chrome.js 2.73 kB 0 B
packages/core/dist/error-tracking/parsers/chrome.mjs 1.32 kB 0 B
packages/core/dist/error-tracking/parsers/gecko.js 2.47 kB 0 B
packages/core/dist/error-tracking/parsers/gecko.mjs 1.13 kB 0 B
packages/core/dist/error-tracking/parsers/index.js 4.75 kB 0 B
packages/core/dist/error-tracking/parsers/index.mjs 2.1 kB 0 B
packages/core/dist/error-tracking/parsers/node.js 4.21 kB 0 B
packages/core/dist/error-tracking/parsers/node.mjs 2.95 kB 0 B
packages/core/dist/error-tracking/parsers/opera.js 2.26 kB 0 B
packages/core/dist/error-tracking/parsers/opera.mjs 746 B 0 B
packages/core/dist/error-tracking/parsers/safari.js 1.88 kB 0 B
packages/core/dist/error-tracking/parsers/safari.mjs 574 B 0 B
packages/core/dist/error-tracking/parsers/winjs.js 1.72 kB 0 B
packages/core/dist/error-tracking/parsers/winjs.mjs 426 B 0 B
packages/core/dist/error-tracking/types.js 1.33 kB 0 B
packages/core/dist/error-tracking/types.mjs 131 B 0 B
packages/core/dist/error-tracking/utils.js 1.8 kB 0 B
packages/core/dist/error-tracking/utils.mjs 604 B 0 B
packages/core/dist/eventemitter.js 1.78 kB 0 B
packages/core/dist/eventemitter.mjs 571 B 0 B
packages/core/dist/featureFlagUtils.js 7.74 kB 0 B
packages/core/dist/featureFlagUtils.mjs 4.94 kB 0 B
packages/core/dist/gzip.js 5.73 kB 0 B
packages/core/dist/gzip.mjs 3.85 kB 0 B
packages/core/dist/index.js 18.3 kB 0 B
packages/core/dist/index.mjs 1.87 kB 0 B
packages/core/dist/logs/index.js 10.9 kB 0 B
packages/core/dist/logs/index.mjs 9.22 kB 0 B
packages/core/dist/logs/logs-utils.js 7.01 kB 0 B
packages/core/dist/logs/logs-utils.mjs 4.85 kB 0 B
packages/core/dist/logs/types.js 603 B 0 B
packages/core/dist/logs/types.mjs 0 B 0 B 🆕
packages/core/dist/metrics/config.js 1.95 kB 0 B
packages/core/dist/metrics/config.mjs 735 B 0 B
packages/core/dist/metrics/index.js 14.4 kB 0 B
packages/core/dist/metrics/index.mjs 12 kB 0 B
packages/core/dist/metrics/metrics-utils.js 3.86 kB 0 B
packages/core/dist/metrics/metrics-utils.mjs 1.97 kB 0 B
packages/core/dist/metrics/types.js 603 B 0 B
packages/core/dist/metrics/types.mjs 0 B 0 B 🆕
packages/core/dist/posthog-core-stateless.js 41.7 kB 0 B
packages/core/dist/posthog-core-stateless.mjs 38.7 kB 0 B
packages/core/dist/posthog-core.js 48.1 kB 0 B
packages/core/dist/posthog-core.mjs 42.6 kB 0 B
packages/core/dist/surveys/activation.js 1.86 kB 0 B
packages/core/dist/surveys/activation.mjs 408 B 0 B
packages/core/dist/surveys/events.js 4.21 kB 0 B
packages/core/dist/surveys/events.mjs 1.99 kB 0 B
packages/core/dist/surveys/index.js 5.53 kB 0 B
packages/core/dist/surveys/index.mjs 1.16 kB 0 B
packages/core/dist/surveys/keys.js 1.7 kB 0 B
packages/core/dist/surveys/keys.mjs 350 B 0 B
packages/core/dist/surveys/translations.js 10 kB 0 B
packages/core/dist/surveys/translations.mjs 7.55 kB 0 B
packages/core/dist/surveys/validation.js 3.06 kB 0 B
packages/core/dist/surveys/validation.mjs 1.51 kB 0 B
packages/core/dist/testing/index.js 2.93 kB 0 B
packages/core/dist/testing/index.mjs 79 B 0 B
packages/core/dist/testing/PostHogCoreTestClient.js 3.24 kB 0 B
packages/core/dist/testing/PostHogCoreTestClient.mjs 1.83 kB 0 B
packages/core/dist/testing/test-utils.js 2.83 kB 0 B
packages/core/dist/testing/test-utils.mjs 1.15 kB 0 B
packages/core/dist/tracing-headers.js 3.38 kB 0 B
packages/core/dist/tracing-headers.mjs 2.08 kB 0 B
packages/core/dist/types.js 8.21 kB 0 B
packages/core/dist/types.mjs 5.09 kB 0 B
packages/core/dist/utils/bot-detection.js 3.28 kB 0 B
packages/core/dist/utils/bot-detection.mjs 1.95 kB 0 B
packages/core/dist/utils/bucketed-rate-limiter.js 4.23 kB 0 B
packages/core/dist/utils/bucketed-rate-limiter.mjs 2.22 kB 0 B
packages/core/dist/utils/index.js 13.5 kB 0 B
packages/core/dist/utils/index.mjs 2.4 kB 0 B
packages/core/dist/utils/logger.js 2.58 kB 0 B
packages/core/dist/utils/logger.mjs 1.29 kB 0 B
packages/core/dist/utils/number-utils.js 3.32 kB 0 B
packages/core/dist/utils/number-utils.mjs 1.68 kB 0 B
packages/core/dist/utils/promise-queue.js 2.48 kB 0 B
packages/core/dist/utils/promise-queue.mjs 1.25 kB 0 B
packages/core/dist/utils/string-utils.js 3.73 kB 0 B
packages/core/dist/utils/string-utils.mjs 1.97 kB 0 B
packages/core/dist/utils/type-utils.js 7.43 kB 0 B
packages/core/dist/utils/type-utils.mjs 3.28 kB 0 B
packages/core/dist/utils/user-agent-utils.js 17.7 kB 0 B
packages/core/dist/utils/user-agent-utils.mjs 14.2 kB 0 B
packages/core/dist/vendor/uuidv7.js 8.29 kB 0 B
packages/core/dist/vendor/uuidv7.mjs 6.72 kB 0 B
packages/mcp/dist/extensions/capture.js 3.75 kB 0 B
packages/mcp/dist/extensions/capture.mjs 2.32 kB 0 B
packages/mcp/dist/extensions/compatibility.js 5.63 kB 0 B
packages/mcp/dist/extensions/compatibility.mjs 3.79 kB 0 B
packages/mcp/dist/extensions/constants.js 4.68 kB 0 B
packages/mcp/dist/extensions/constants.mjs 2.44 kB 0 B
packages/mcp/dist/extensions/context-parameters.js 3.9 kB 0 B
packages/mcp/dist/extensions/context-parameters.mjs 2.11 kB 0 B
packages/mcp/dist/extensions/conversation-id.js 7.12 kB 0 B
packages/mcp/dist/extensions/conversation-id.mjs 4.21 kB 0 B
packages/mcp/dist/extensions/event-types.js 1.68 kB 0 B
packages/mcp/dist/extensions/event-types.mjs 459 B 0 B
packages/mcp/dist/extensions/exceptions.js 2.57 kB 0 B
packages/mcp/dist/extensions/exceptions.mjs 1.19 kB 0 B
packages/mcp/dist/extensions/ids.js 2.01 kB 0 B
packages/mcp/dist/extensions/ids.mjs 637 B 0 B
packages/mcp/dist/extensions/instrument-highlevel.js 11.3 kB 0 B
packages/mcp/dist/extensions/instrument-highlevel.mjs 8.71 kB 0 B
packages/mcp/dist/extensions/instrument-********.js 4.25 kB 0 B
packages/mcp/dist/extensions/instrument-********.mjs 2.43 kB 0 B
packages/mcp/dist/extensions/instrumentation.js 18.4 kB 0 B
packages/mcp/dist/extensions/instrumentation.mjs 13.8 kB 0 B
packages/mcp/dist/extensions/intent.js 3.31 kB 0 B
packages/mcp/dist/extensions/intent.mjs 1.68 kB 0 B
packages/mcp/dist/extensions/internal.js 6.65 kB 0 B
packages/mcp/dist/extensions/internal.mjs 4.4 kB 0 B
packages/mcp/dist/extensions/lib-********.js 1.6 kB 0 B
packages/mcp/dist/extensions/lib-********.mjs 267 B 0 B
packages/mcp/dist/extensions/logger.js 1.44 kB 0 B
packages/mcp/dist/extensions/logger.mjs 204 B 0 B
packages/mcp/dist/extensions/mcp-********.js 3.93 kB 0 B
packages/mcp/dist/extensions/mcp-********.mjs 2.56 kB 0 B
packages/mcp/dist/extensions/mcp-sdk-compat.js 4.08 kB 0 B
packages/mcp/dist/extensions/mcp-sdk-compat.mjs 2.22 kB 0 B
packages/mcp/dist/extensions/posthog-events.js 10.8 kB 0 B
packages/mcp/dist/extensions/posthog-events.mjs 7.35 kB 0 B
packages/mcp/dist/extensions/posthog-mcp.js 6.65 kB 0 B
packages/mcp/dist/extensions/posthog-mcp.mjs 4.74 kB 0 B
packages/mcp/dist/extensions/sanitization.js 4.04 kB 0 B
packages/mcp/dist/extensions/sanitization.mjs 2.46 kB 0 B
packages/mcp/dist/extensions/session-token.js 5.72 kB 0 B
packages/mcp/dist/extensions/session-token.mjs 4 kB 0 B
packages/mcp/dist/extensions/session.js 4.72 kB 0 B
packages/mcp/dist/extensions/session.mjs 2.77 kB 0 B
packages/mcp/dist/extensions/sink.js 4.38 kB 0 B
packages/mcp/dist/extensions/sink.mjs 2.54 kB 0 B
packages/mcp/dist/extensions/tools.js 3.5 kB 0 B
packages/mcp/dist/extensions/tools.mjs 1.61 kB 0 B
packages/mcp/dist/extensions/tracing-helpers.js 2.41 kB 0 B
packages/mcp/dist/extensions/tracing-helpers.mjs 772 B 0 B
packages/mcp/dist/extensions/truncation.js 11.2 kB 0 B
packages/mcp/dist/extensions/truncation.mjs 9.54 kB 0 B
packages/mcp/dist/index.js 8.45 kB 0 B
packages/mcp/dist/index.mjs 4.63 kB 0 B
packages/mcp/dist/types.js 603 B 0 B
packages/mcp/dist/types.mjs 0 B 0 B 🆕
packages/mcp/dist/version.js 1.21 kB 0 B
packages/mcp/dist/version.mjs 46 B 0 B
packages/next/dist/app/PostHogProvider.js 5.37 kB 0 B
packages/next/dist/client/ClientPostHogProvider.js 2.28 kB 0 B
packages/next/dist/client/hooks.js 172 B 0 B
packages/next/dist/client/PostHogPageView.js 1.76 kB 0 B
packages/next/dist/index.client.js 401 B 0 B
packages/next/dist/index.edge.js 570 B 0 B
packages/next/dist/index.js 554 B 0 B
packages/next/dist/index.react-server.js 420 B 0 B
packages/next/dist/middleware/postHogMiddleware.js 3.68 kB 0 B
packages/next/dist/pages.client.js 225 B 0 B
packages/next/dist/pages.edge.js 294 B 0 B
packages/next/dist/pages.js 347 B 0 B
packages/next/dist/pages/createPostHog.js 1.48 kB 0 B
packages/next/dist/pages/getServerSidePostHog.js 1.48 kB 0 B
packages/next/dist/pages/PostHogPageView.js 1.55 kB 0 B
packages/next/dist/pages/PostHogProvider.js 1.58 kB 0 B
packages/next/dist/server.edge.js 795 B 0 B
packages/next/dist/server/captureRequestError.js 5.26 kB 0 B
packages/next/dist/server/clientCache.edge.js 305 B 0 B
packages/next/dist/server/clientCache.js 1.54 kB 0 B
packages/next/dist/server/clientCache.node.js 305 B 0 B
packages/next/dist/server/createPostHog.js 1.44 kB 0 B
packages/next/dist/server/getPostHog.js 3.45 kB 0 B
packages/next/dist/server/onRequestError.js 1.39 kB 0 B
packages/next/dist/server/onRequestError.types.js 59 B 0 B
packages/next/dist/shared/browser.js 195 B 0 B
packages/next/dist/shared/config.js 2.23 kB 0 B
packages/next/dist/shared/constants.js 201 B 0 B
packages/next/dist/shared/cookie.js 540 B 0 B
packages/next/dist/shared/identity.js 2.56 kB 0 B
packages/next/dist/shared/tracing-headers.js 2.18 kB 0 B
packages/nextjs-config/dist/config.js 6.1 kB 0 B
packages/nextjs-config/dist/config.mjs 4.53 kB 0 B
packages/nextjs-config/dist/index.js 2.24 kB 0 B
packages/nextjs-config/dist/index.mjs 30 B 0 B
packages/nextjs-config/dist/strip-sourcemap-********.js 3.63 kB 0 B
packages/nextjs-config/dist/strip-sourcemap-********.mjs 1.77 kB 0 B
packages/nextjs-config/dist/utils.js 2.94 kB 0 B
packages/nextjs-config/dist/utils.mjs 826 B 0 B
packages/node/dist/capture-v1/config.js 1.5 kB 0 B
packages/node/dist/capture-v1/config.mjs 292 B 0 B
packages/node/dist/capture-v1/errors.js 1.89 kB 0 B
packages/node/dist/capture-v1/errors.mjs 694 B 0 B
packages/node/dist/capture-v1/routing.js 1.68 kB 0 B
packages/node/dist/capture-v1/routing.mjs 279 B 0 B
packages/node/dist/capture-v1/sender.js 9.22 kB 0 B
packages/node/dist/capture-v1/sender.mjs 7.75 kB 0 B
packages/node/dist/capture-v1/transform.js 4.86 kB 0 B
packages/node/dist/capture-v1/transform.mjs 3.38 kB 0 B
packages/node/dist/capture-v1/types.js 603 B 0 B
packages/node/dist/capture-v1/types.mjs 0 B 0 B 🆕
packages/node/dist/client.js 54.7 kB 0 B
packages/node/dist/client.mjs 51.9 kB 0 B
packages/node/dist/entrypoints/index.edge.js 3.85 kB 0 B
packages/node/dist/entrypoints/index.edge.mjs 720 B 0 B
packages/node/dist/entrypoints/index.node.js 5.67 kB 0 B
packages/node/dist/entrypoints/index.node.mjs 1.25 kB 0 B
packages/node/dist/entrypoints/nestjs.js 2.31 kB 0 B
packages/node/dist/entrypoints/nestjs.mjs 42 B 0 B
packages/node/dist/experimental.js 870 B 0 B
packages/node/dist/experimental.mjs 267 B 0 B
packages/node/dist/exports.js 6.75 kB 0 B
packages/node/dist/exports.mjs 582 B 0 B
packages/node/dist/extensions/context/context.js 2.13 kB 0 B
packages/node/dist/extensions/context/context.mjs 863 B 0 B
packages/node/dist/extensions/context/types.js 603 B 0 B
packages/node/dist/extensions/context/types.mjs 0 B 0 B 🆕
packages/node/dist/extensions/error-tracking/autocapture.js 2.66 kB 0 B
packages/node/dist/extensions/error-tracking/autocapture.mjs 1.24 kB 0 B
packages/node/dist/extensions/error-tracking/index.js 4.21 kB 0 B
packages/node/dist/extensions/error-tracking/index.mjs 2.95 kB 0 B
packages/node/dist/extensions/error-tracking/modifiers/context-lines.node.js 8.81 kB 0 B
packages/node/dist/extensions/error-tracking/modifiers/context-lines.node.mjs 7.15 kB 0 B
packages/node/dist/extensions/error-tracking/modifiers/module.node.js 2.78 kB 0 B
packages/node/dist/extensions/error-tracking/modifiers/module.node.mjs 1.45 kB 0 B
packages/node/dist/extensions/error-tracking/modifiers/relative-path.node.js 1.97 kB 0 B
packages/node/dist/extensions/error-tracking/modifiers/relative-path.node.mjs 624 B 0 B
packages/node/dist/extensions/express.js 4.97 kB 0 B
packages/node/dist/extensions/express.mjs 2.78 kB 0 B
packages/node/dist/extensions/feature-flags/cache.js 603 B 0 B
packages/node/dist/extensions/feature-flags/cache.mjs 0 B 0 B 🆕
packages/node/dist/extensions/feature-flags/crypto.js 1.57 kB 0 B
packages/node/dist/extensions/feature-flags/crypto.mjs 395 B 0 B
packages/node/dist/extensions/feature-flags/feature-flags.js 41.3 kB 0 B
packages/node/dist/extensions/feature-flags/feature-flags.mjs 39.2 kB 0 B
packages/node/dist/extensions/nestjs.js 5.36 kB 0 B
packages/node/dist/extensions/nestjs.mjs 3.18 kB 0 B
packages/node/dist/extensions/sentry-integration.js 4.66 kB 0 B
packages/node/dist/extensions/sentry-integration.mjs 3.17 kB 0 B
packages/node/dist/extensions/tracing-headers.js 3.31 kB 0 B
packages/node/dist/extensions/tracing-headers.mjs 1.53 kB 0 B
packages/node/dist/extensions/url-utils.js 2.22 kB 0 B
packages/node/dist/extensions/url-utils.mjs 785 B 0 B
packages/node/dist/feature-flag-evaluations.js 6.08 kB 0 B
packages/node/dist/feature-flag-evaluations.mjs 4.74 kB 0 B
packages/node/dist/storage-memory.js 1.52 kB 0 B
packages/node/dist/storage-memory.mjs 297 B 0 B
packages/node/dist/types.js 1.43 kB 0 B
packages/node/dist/types.mjs 224 B 0 B
packages/node/dist/version.js 1.21 kB 0 B
packages/node/dist/version.mjs 46 B 0 B
packages/nuxt/dist/module.mjs 5.35 kB 0 B
packages/nuxt/dist/runtime/composables/useFeatureFlagEnabled.js 566 B 0 B
packages/nuxt/dist/runtime/composables/useFeatureFlagPayload.js 690 B 0 B
packages/nuxt/dist/runtime/composables/useFeatureFlagVariantKey.js 591 B 0 B
packages/nuxt/dist/runtime/composables/usePostHog.js 128 B 0 B
packages/nuxt/dist/runtime/nitro-plugin.js 1.08 kB 0 B
packages/nuxt/dist/runtime/vue-plugin.js 1.14 kB 0 B
packages/openfeature-node-provider/dist/index.js 1.76 kB 0 B
packages/openfeature-node-provider/dist/index.mjs 190 B 0 B
packages/openfeature-node-provider/dist/mapping.js 5.32 kB 0 B
packages/openfeature-node-provider/dist/mapping.mjs 3.21 kB 0 B
packages/openfeature-node-provider/dist/provider.js 3.99 kB 0 B
packages/openfeature-node-provider/dist/provider.mjs 2.6 kB 0 B
packages/openfeature-web-provider/dist/index.js 1.75 kB 0 B
packages/openfeature-web-provider/dist/index.mjs 184 B 0 B
packages/openfeature-web-provider/dist/mapping.js 5.29 kB 0 B
packages/openfeature-web-provider/dist/mapping.mjs 3.18 kB 0 B
packages/openfeature-web-provider/dist/provider.js 4.41 kB 0 B
packages/openfeature-web-provider/dist/provider.mjs 3.06 kB 0 B
packages/plugin-utils/dist/cli.js 3.14 kB 0 B
packages/plugin-utils/dist/cli.mjs 1.64 kB 0 B
packages/plugin-utils/dist/config.js 3.07 kB 0 B
packages/plugin-utils/dist/config.mjs 1.83 kB 0 B
packages/plugin-utils/dist/index.js 4.3 kB 0 B
packages/plugin-utils/dist/index.mjs 217 B 0 B
packages/plugin-utils/dist/spawn-local.js 2.17 kB 0 B
packages/plugin-utils/dist/spawn-local.mjs 918 B 0 B
packages/plugin-utils/dist/utils.js 3.27 kB 0 B
packages/plugin-utils/dist/utils.mjs 1.3 kB 0 B
packages/react-native/dist/autocapture.js 6.27 kB 0 B
packages/react-native/dist/error-tracking/index.js 9.97 kB 0 B
packages/react-native/dist/error-tracking/utils.js 2.58 kB 0 B
packages/react-native/dist/frameworks/wix-navigation.js 1.3 kB 0 B
packages/react-native/dist/hooks/useFeatureFlag.js 1.84 kB 0 B
packages/react-native/dist/hooks/useFeatureFlagResult.js 963 B 0 B
packages/react-native/dist/hooks/useFeatureFlags.js 921 B 0 B
packages/react-native/dist/hooks/useNavigationTracker.js 2.45 kB 0 B
packages/react-native/dist/hooks/usePostHog.js 544 B 0 B
packages/react-native/dist/hooks/utils.js 988 B 0 B
packages/react-native/dist/index.js 4.33 kB 0 B
packages/react-native/dist/logs-********.js 3.66 kB 0 B
packages/react-native/dist/native-deps.js 8.73 kB 0 B
packages/react-native/dist/optional/OptionalAsyncStorage.js 299 B 0 B
packages/react-native/dist/optional/OptionalExpoApplication.js 377 B 0 B
packages/react-native/dist/optional/OptionalExpoDevice.js 347 B 0 B
packages/react-native/dist/optional/OptionalExpoFileSystem.js 386 B 0 B
packages/react-native/dist/optional/OptionalExpoFileSystemLegacy.js 423 B 0 B
packages/react-native/dist/optional/OptionalExpoLocalization.js 383 B 0 B
packages/react-native/dist/optional/OptionalPlugin.js 569 B 0 B
packages/react-native/dist/optional/OptionalReactNativeDeviceInfo.js 415 B 0 B
packages/react-native/dist/optional/OptionalReactNativeLocalize.js 303 B 0 B
packages/react-native/dist/optional/OptionalReactNativeNavigation.js 415 B 0 B
packages/react-native/dist/optional/OptionalReactNativeNavigationWix.js 443 B 0 B
packages/react-native/dist/optional/OptionalReactNativeSafeArea.js 644 B 0 B
packages/react-native/dist/optional/OptionalReactNativeSvg.js 872 B 0 B
packages/react-native/dist/posthog-rn.js 55.3 kB 0 B
packages/react-native/dist/PostHogContext.js 329 B 0 B
packages/react-native/dist/PostHogErrorBoundary.js 3.19 kB 0 B
packages/react-native/dist/PostHogMaskView.js 1.68 kB 0 B
packages/react-native/dist/PostHogProvider.js 4.55 kB 0 B
packages/react-native/dist/storage.js 5.76 kB 0 B
packages/react-native/dist/surveys/components/BottomSection.js 1.51 kB 0 B
packages/react-native/dist/surveys/components/Cancel.js 968 B 0 B
packages/react-native/dist/surveys/components/ConfirmationMessage.js 1.71 kB 0 B
packages/react-native/dist/surveys/components/QuestionHeader.js 1.43 kB 0 B
packages/react-native/dist/surveys/components/QuestionTypes.js 14 kB 0 B
packages/react-native/dist/surveys/components/SurveyModal.js 6.66 kB 0 B
packages/react-native/dist/surveys/components/Surveys.js 6.58 kB 0 B
packages/react-native/dist/surveys/getActiveMatchingSurveys.js 2.73 kB 0 B
packages/react-native/dist/surveys/icons.js 10 kB 0 B
packages/react-native/dist/surveys/index.js 600 B 0 B
packages/react-native/dist/surveys/PostHogSurveyProvider.js 6.28 kB 0 B
packages/react-native/dist/surveys/safeStyleSheet.js 448 B 0 B
packages/react-native/dist/surveys/survey-translations.js 1.11 kB 0 B
packages/react-native/dist/surveys/surveys-utils.js 13.6 kB 0 B
packages/react-native/dist/surveys/useActivatedSurveys.js 3.73 kB 0 B
packages/react-native/dist/surveys/useSurveyStorage.js 2.48 kB 0 B
packages/react-native/dist/tooling/expoconfig.js 16.8 kB 0 B
packages/react-native/dist/tooling/metroconfig.js 2.32 kB 0 B
packages/react-native/dist/tooling/posthogMetroSerializer.js 4.86 kB 0 B
packages/react-native/dist/tooling/utils.js 4.05 kB 0 B
packages/react-native/dist/tooling/vendor/expo/expoconfig.js 70 B 0 B
packages/react-native/dist/tooling/vendor/metro/countLines.js 237 B 0 B
packages/react-native/dist/tooling/vendor/metro/utils.js 3.35 kB 0 B
packages/react-native/dist/types.js 70 B 0 B
packages/react-native/dist/utils.js 1.3 kB 0 B
packages/react-native/dist/version.js 130 B 0 B
packages/react/dist/esm/index.js 21.1 kB 0 B
packages/react/dist/esm/slim/index.js 17.5 kB 0 B
packages/react/dist/esm/surveys/index.js 4.68 kB 0 B
packages/react/dist/umd/index.js 24.4 kB 0 B
packages/react/dist/umd/slim/index.js 20.3 kB 0 B
packages/react/dist/umd/surveys/index.js 5.45 kB 0 B
packages/rollup-plugin/dist/index.js 2.47 kB 0 B
packages/rrweb/all/dist/rrweb-all.cjs 638 kB 0 B
packages/rrweb/all/dist/rrweb-all.js 638 kB 0 B
packages/rrweb/all/dist/rrweb-all.umd.cjs 641 kB 0 B
packages/rrweb/all/dist/rrweb-all.umd.min.cjs 301 kB 0 B
packages/rrweb/packer/dist/base-********.js 18.2 kB 0 B
packages/rrweb/packer/dist/base-********.cjs 18.3 kB 0 B
packages/rrweb/packer/dist/base-********.umd.cjs 18.7 kB 0 B
packages/rrweb/packer/dist/base-********.umd.min.cjs 9.5 kB 0 B
packages/rrweb/packer/dist/pack.cjs 347 B 0 B
packages/rrweb/packer/dist/pack.js 285 B 0 B
packages/rrweb/packer/dist/pack.umd.cjs 1.63 kB 0 B
packages/rrweb/packer/dist/pack.umd.min.cjs 1.11 kB 0 B
packages/rrweb/packer/dist/packer.cjs 257 B 0 B
packages/rrweb/packer/dist/packer.js 136 B 0 B
packages/rrweb/packer/dist/packer.umd.cjs 662 B 0 B
packages/rrweb/packer/dist/packer.umd.min.cjs 626 B 0 B
packages/rrweb/packer/dist/unpack.cjs 769 B 0 B
packages/rrweb/packer/dist/unpack.js 702 B 0 B
packages/rrweb/packer/dist/unpack.umd.cjs 1.17 kB 0 B
packages/rrweb/packer/dist/unpack.umd.min.cjs 955 B 0 B
packages/rrweb/plugins/rrweb-plugin-canvas-webrtc-record/dist/rrweb-plugin-canvas-webrtc-record.cjs 37.6 kB 0 B
packages/rrweb/plugins/rrweb-plugin-canvas-webrtc-record/dist/rrweb-plugin-canvas-webrtc-record.js 37.5 kB 0 B
packages/rrweb/plugins/rrweb-plugin-canvas-webrtc-record/dist/rrweb-plugin-canvas-webrtc-record.umd.cjs 38 kB 0 B
packages/rrweb/plugins/rrweb-plugin-canvas-webrtc-record/dist/rrweb-plugin-canvas-webrtc-record.umd.min.cjs 22.2 kB 0 B
packages/rrweb/plugins/rrweb-plugin-canvas-webrtc-replay/dist/rrweb-plugin-canvas-webrtc-replay.cjs 34.3 kB 0 B
packages/rrweb/plugins/rrweb-plugin-canvas-webrtc-replay/dist/rrweb-plugin-canvas-webrtc-replay.js 34.2 kB 0 B
packages/rrweb/plugins/rrweb-plugin-canvas-webrtc-replay/dist/rrweb-plugin-canvas-webrtc-replay.umd.cjs 34.7 kB 0 B
packages/rrweb/plugins/rrweb-plugin-canvas-webrtc-replay/dist/rrweb-plugin-canvas-webrtc-replay.umd.min.cjs 20.5 kB 0 B
packages/rrweb/plugins/rrweb-plugin-console-record/dist/rrweb-plugin-console-record.cjs 15.6 kB 0 B
packages/rrweb/plugins/rrweb-plugin-console-record/dist/rrweb-plugin-console-record.js 15.5 kB 0 B
packages/rrweb/plugins/rrweb-plugin-console-record/dist/rrweb-plugin-console-record.umd.cjs 16.1 kB 0 B
packages/rrweb/plugins/rrweb-plugin-console-record/dist/rrweb-plugin-console-record.umd.min.cjs 7.61 kB 0 B
packages/rrweb/plugins/rrweb-plugin-console-replay/dist/rrweb-plugin-console-replay.cjs 5.01 kB 0 B
packages/rrweb/plugins/rrweb-plugin-console-replay/dist/rrweb-plugin-console-replay.js 4.9 kB 0 B
packages/rrweb/plugins/rrweb-plugin-console-replay/dist/rrweb-plugin-console-replay.umd.cjs 5.44 kB 0 B
packages/rrweb/plugins/rrweb-plugin-console-replay/dist/rrweb-plugin-console-replay.umd.min.cjs 2.64 kB 0 B
packages/rrweb/plugins/rrweb-plugin-sequential-id-record/dist/rrweb-plugin-sequential-id-record.cjs 681 B 0 B
packages/rrweb/plugins/rrweb-plugin-sequential-id-record/dist/rrweb-plugin-sequential-id-record.js 548 B 0 B
packages/rrweb/plugins/rrweb-plugin-sequential-id-record/dist/rrweb-plugin-sequential-id-record.umd.cjs 1.12 kB 0 B
packages/rrweb/plugins/rrweb-plugin-sequential-id-record/dist/rrweb-plugin-sequential-id-record.umd.min.cjs 829 B 0 B
packages/rrweb/plugins/rrweb-plugin-sequential-id-replay/dist/rrweb-plugin-sequential-id-replay.cjs 933 B 0 B
packages/rrweb/plugins/rrweb-plugin-sequential-id-replay/dist/rrweb-plugin-sequential-id-replay.js 820 B 0 B
packages/rrweb/plugins/rrweb-plugin-sequential-id-replay/dist/rrweb-plugin-sequential-id-replay.umd.cjs 1.37 kB 0 B
packages/rrweb/plugins/rrweb-plugin-sequential-id-replay/dist/rrweb-plugin-sequential-id-replay.umd.min.cjs 968 B 0 B
packages/rrweb/record/dist/rrweb-record.cjs 190 kB 0 B
packages/rrweb/record/dist/rrweb-record.js 189 kB 0 B
packages/rrweb/record/dist/rrweb-record.umd.cjs 190 kB 0 B
packages/rrweb/record/dist/rrweb-record.umd.min.cjs 90.2 kB 0 B
packages/rrweb/replay/dist/rrweb-replay.cjs 452 kB 0 B
packages/rrweb/replay/dist/rrweb-replay.js 452 kB 0 B
packages/rrweb/replay/dist/rrweb-replay.umd.cjs 454 kB 0 B
packages/rrweb/replay/dist/rrweb-replay.umd.min.cjs 214 kB 0 B
packages/rrweb/rrdom-nodejs/dist/rrdom-nodejs.cjs 153 kB 0 B
packages/rrweb/rrdom-nodejs/dist/rrdom-nodejs.js 152 kB 0 B
packages/rrweb/rrdom-nodejs/dist/rrdom-nodejs.umd.cjs 154 kB 0 B
packages/rrweb/rrdom-nodejs/dist/rrdom-nodejs.umd.min.cjs 71.7 kB 0 B
packages/rrweb/rrdom/dist/rrdom.cjs 178 kB 0 B
packages/rrweb/rrdom/dist/rrdom.js 177 kB 0 B
packages/rrweb/rrdom/dist/rrdom.umd.cjs 179 kB 0 B
packages/rrweb/rrdom/dist/rrdom.umd.min.cjs 82.3 kB 0 B
packages/rrweb/rrweb-snapshot/dist/record.cjs 34.5 kB 0 B
packages/rrweb/rrweb-snapshot/dist/record.js 33.4 kB 0 B
packages/rrweb/rrweb-snapshot/dist/record.umd.cjs 57 kB 0 B
packages/rrweb/rrweb-snapshot/dist/record.umd.min.cjs 26.9 kB 0 B
packages/rrweb/rrweb-snapshot/dist/replay.cjs 141 kB 0 B
packages/rrweb/rrweb-snapshot/dist/replay.js 140 kB 0 B
packages/rrweb/rrweb-snapshot/dist/replay.umd.cjs 165 kB 0 B
packages/rrweb/rrweb-snapshot/dist/replay.umd.min.cjs 75.5 kB 0 B
packages/rrweb/rrweb-snapshot/dist/rrweb-********.cjs 2.27 kB 0 B
packages/rrweb/rrweb-snapshot/dist/rrweb-********.js 1.42 kB 0 B
packages/rrweb/rrweb-snapshot/dist/rrweb-********.umd.cjs 224 kB 0 B
packages/rrweb/rrweb-snapshot/dist/rrweb-********.umd.min.cjs 94.1 kB 0 B
packages/rrweb/rrweb-snapshot/dist/types-********.cjs 19.4 kB 0 B
packages/rrweb/rrweb-snapshot/dist/types-********.umd.cjs 19.9 kB 0 B
packages/rrweb/rrweb-snapshot/dist/types-********.umd.min.cjs 9.84 kB 0 B
packages/rrweb/rrweb-snapshot/dist/types-********.js 19 kB 0 B
packages/rrweb/rrweb/dist/rrweb.cjs 622 kB 0 B
packages/rrweb/rrweb/dist/rrweb.js 621 kB 0 B
packages/rrweb/rrweb/dist/rrweb.umd.cjs 622 kB 0 B
packages/rrweb/rrweb/dist/rrweb.umd.min.cjs 292 kB 0 B
packages/rrweb/types/dist/rrweb-types.cjs 5.75 kB 0 B
packages/rrweb/types/dist/rrweb-types.js 5.46 kB 0 B
packages/rrweb/types/dist/rrweb-types.umd.cjs 6.16 kB 0 B
packages/rrweb/types/dist/rrweb-types.umd.min.cjs 2.86 kB 0 B
packages/rrweb/utils/dist/rrweb-utils.cjs 7.48 kB 0 B
packages/rrweb/utils/dist/rrweb-utils.js 7.01 kB 0 B
packages/rrweb/utils/dist/rrweb-utils.umd.cjs 7.89 kB 0 B
packages/rrweb/utils/dist/rrweb-utils.umd.min.cjs 4.01 kB 0 B
packages/types/dist/capture-log.js 603 B 0 B
packages/types/dist/capture-log.mjs 0 B 0 B 🆕
packages/types/dist/capture-metric.js 1.37 kB 0 B
packages/types/dist/capture-metric.mjs 93 B 0 B
packages/types/dist/capture.js 603 B 0 B
packages/types/dist/capture.mjs 0 B 0 B 🆕
packages/types/dist/common.js 603 B 0 B
packages/types/dist/common.mjs 0 B 0 B 🆕
packages/types/dist/feature-flags.js 603 B 0 B
packages/types/dist/feature-flags.mjs 0 B 0 B 🆕
packages/types/dist/index.js 1.45 kB 0 B
packages/types/dist/index.mjs 122 B 0 B
packages/types/dist/posthog-config.js 603 B 0 B
packages/types/dist/posthog-config.mjs 0 B 0 B 🆕
packages/types/dist/posthog.js 603 B 0 B
packages/types/dist/posthog.mjs 0 B 0 B 🆕
packages/types/dist/request.js 603 B 0 B
packages/types/dist/request.mjs 0 B 0 B 🆕
packages/types/dist/segment.js 603 B 0 B
packages/types/dist/segment.mjs 0 B 0 B 🆕
packages/types/dist/session-recording.js 603 B 0 B
packages/types/dist/session-recording.mjs 0 B 0 B 🆕
packages/types/dist/survey.js 603 B 0 B
packages/types/dist/survey.mjs 0 B 0 B 🆕
packages/types/dist/toolbar.js 603 B 0 B
packages/types/dist/toolbar.mjs 0 B 0 B 🆕
packages/types/dist/tree-shakeable.js 603 B 0 B
packages/types/dist/tree-shakeable.mjs 0 B 0 B 🆕
packages/web/dist/index.cjs 14 kB 0 B
packages/web/dist/index.mjs 14 kB 0 B
packages/webpack-plugin/dist/config.js 1.47 kB 0 B
packages/webpack-plugin/dist/config.mjs 480 B 0 B
packages/webpack-plugin/dist/index.js 6.7 kB 0 B
packages/webpack-plugin/dist/index.mjs 2.94 kB 0 B
tooling/changelog/dist/index.js 3.31 kB 0 B
tooling/rollup-utils/dist/index.js 1.17 kB 0 B

compressed-size-action

@posthog

posthog Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

🦔 PostHog Review reviewed this pull request

Found 0 must fix, 1 should fix, 1 consider.

Published 2 findings (view the review).

@posthog

posthog Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

PostHog Review alpha 🦔 If you find any issues helpful - please reply "valid", "invalid", etc., for evaluation purposes 🙏

@posthog posthog Bot 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.

PostHog Review

Found 1 should fix, 1 consider.

Other findings (outside the changed lines)

Valid issues on this PR's files that sit on lines GitHub won't let us comment on inline.

Preserve URL-trigger activation during the re-entrant restart

Priority: should_fix | File: packages/browser/src/extensions/replay/external/lazy-loaded-session-recorder.ts:1207-1220 | Category: bug

Why we think it's a valid issue
  • Checked: The whole re-entrant chain, link by link: _onSessionIdCallback ordering, _updateWindowAndSessionIds' restart, _startRecorder, rrweb's record() in packages/rrweb/rrweb/src/record/index.ts, onRRwebEmit's trigger check, URLTriggerMatching.checkUrlTriggerConditions/stop, _activateTrigger, V1RecordingStrategy.stop/clearConditionalRecordingPersistence, AndTriggerMatching.triggerStatus, and _onBeforeUnload.
  • Found: The ordering claim holds. $session_id_change is emitted at :1207, and _clearConditionalRecordingPersistence() runs after it at :1209. The emit re-enters _updateWindowAndSessionIds, which adopts the new ids and calls stop(); start('session_id_changed') (:2030-:2039), all synchronously inside that emit.
  • Found: The restart really does activate the trigger before the clear. rrweb's record() calls init()takeFullSnapshot() inline when document.readyState is interactive or complete (packages/rrweb/rrweb/src/record/index.ts:741-:752), and takeFullSnapshot emits a Meta first (:416-:422). onRRwebEmit runs this._strategy?.checkUrlTriggers(this.sessionId, ...) on every event (:1524) with the already-swapped new id, and _activateTrigger writes SESSION_RECORDING_URL_TRIGGER_ACTIVATED_SESSION: this.sessionId (:930-:934). clearConditionalRecordingPersistence() then unregisters that exact key (recording-strategies.ts:304-:306).
  • Found: The URL cache does block recovery, and the restart is what makes the cache miss happen in the first place. checkUrlTriggerConditions returns early when url === this._lastCheckedUrl (triggerMatching.ts:340-:344); URLTriggerMatching.stop() resets it to '' (:366-:368) and is reached through _teardown_strategy?.stop() (:1264, recording-strategies.ts:321-:326). So the restart clears the cache, the Meta evaluates and activates, the activation is wiped, and the cache is back to the current URL — every later event on that URL skips evaluation. With URL triggers only, AndTriggerMatching drops TRIGGER_DISABLED and reports TRIGGER_PENDING (triggerMatching.ts:152-:167), so the status stays BUFFERING and _onBeforeUnload discards the buffer in that state (:1919-:1922).
  • Found: Not a regression from this PR. On the unfixed code the same configuration was equally dead: in the 'unknown' state no restart ran, _clearConditionalRecordingPersistence() still wiped the activation, and _lastCheckedUrl was never reset, so the recorder sat pending on a stale session id and shipped nothing either. The identical wipe-after-activation interleaving is also already reachable pre-PR for a non-idle recorder whose session rotates on sessionPastMaximumLength.
  • Impact: Confirmed loss of the entire rotated session's recording for V1 URL-trigger configurations when the URL still matches at rotation time and does not change afterwards. The fix is a reordering inside _onSessionIdCallback — the same function whose restart guard this PR rewrites — so the author is well placed to make it.
  • Priority: Lowered to should_fix. The defect is real and fully traced, but this PR does not introduce or worsen the user-visible outcome, and it needs the niche URL-trigger feature plus a matching, unchanging URL, so it should not block this fix for #4202.
Issue description

On a loaded page, rrweb emits the new recorder's Meta snapshot synchronously. That snapshot activates a matching URL trigger for the new session. After $session_id_change returns, _clearConditionalRecordingPersistence() removes the new activation. The matcher already cached the URL, so later events on the same URL skip evaluation. A URL-trigger-only recorder then stays in BUFFERING and does not send the rotated session.

Suggested fix

Flush the old buffer and clear the old session's conditional state before emitting $session_id_change. Then let the re-entrant restart create the new state. Add a test that rotates from 'unknown' on a matching URL and expects a non-buffering status without navigation.

Comment on lines +2016 to +2018
// Only bail on confirmed idle: while 'unknown' the recorder still captures, so it must
// also keep checking for session changes or its events are stamped with a stale session id.
if (this._isIdle === true) {

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.

Flush the old session before adopting the new IDs

consider bug

Why we think it's a valid issue
  • Checked: The flagged lines against the PR diff (gh pr diff 4750), plus stop(), _flushBuffer(), _captureSnapshotBuffered(), _onSessionIdCallback(), get status, allMatchSessionRecordingStatus/anyMatchSessionRecordingStatus, V1RecordingStrategy.makeSamplingDecisions/ensureSamplingDecision, and sampleOnProperty.
  • Found: The mechanism is real. lazy-loaded-session-recorder.ts:2030 assigns this._windowId/this._sessionId, then :2038 calls stop(). stop() runs _flushBuffer() then _clearBuffer() (:1334). _flushBuffer() reads the new id: ensureSamplingDecision(this.sessionId) at :1737 and status at :1645 both use this.sessionId, and _isSampled (:530) decodes the decision against this.sessionId. A sampled-out session returns DISABLED (triggerMatching.ts:671, :714) and a pending trigger returns BUFFERING (:666, :704); both make _flushBuffer return the buffer un-drained (:1740), so the following _clearBuffer() drops it.
  • Found: The buffer is non-empty at that moment. $session_ending is emitted at :1188 before the re-entrant $session_id_change and is appended under the old id (lifecycle events skip _updateWindowAndSessionIds, :1583), so the discarded buffer contains real old-session data plus the session-linking marker.
  • Found: The flagged ordering is NOT introduced by this PR. The diff touches only the guard at :2016 (if (this._isIdle)if (this._isIdle === true)); the assign-then-stop() sequence at :2030-:2039 is unchanged, and it is already the mainstream path whenever _isIdle === false and a session rotates (for example sessionPastMaximumLength while the user is active). The PR only routes the 'unknown' state into the same code.
  • Found: The same trade-off is already deliberate elsewhere in this file: _captureSnapshotBuffered flushes on sessionChanged with the new id in place and explicitly discards a suppressed flush (:1843-:1848, with a comment stating why relabeling would mis-attribute).
  • Found: The suggested fix is only partly effective on the path described. _clearConditionalRecordingPersistence() runs at :1209, before the re-entrant emit, and unregisters the trigger-activated and sampling keys, so an old-id flush would still read trigger-pending → BUFFERING. It does help the sampling case, because sampleOnProperty (extensions/sampling.ts:24) is a deterministic hash of the session id, so re-deciding for the old id reproduces the old decision.
  • Impact: Confirmed data loss, but bounded. Change 3 in this same PR schedules the 2 s flush timer during 'unknown' (RECORDING_BUFFER_TIMEOUT = 2000, :120), so the residual buffer at rotation is the last ≤2 s of old-session events plus $session_ending — not a whole recording. It bites only when sampling or triggers gate the new session.
  • Priority: Lowered to consider. The defect is real and nameable, so it stays on record, but must_fix overstates it: the ordering is pre-existing untouched code shared with the already-reachable _isIdle === false rotation path, the loss is the tail of a session that ends anyway, and the codebase already accepts this discard at :1843. Reordering stop() changes rotation semantics for every idle state and needs its own tests, which is wider than this targeted fix for Replay full snapshot remains on previous session after idle rotation in 1.404.1 #4202.
Issue description

Real rrweb re-enters _updateWindowAndSessionIds during $session_id_change. This new path replaces the IDs before stop() flushes the old buffer. _flushBuffer() then evaluates the new session's sampling and trigger state. A sampled-out or trigger-pending new session suppresses the flush. stop() then discards valid old-session data.

Suggested fix

Call stop() while the recorder still has the old IDs. Assign the new IDs after that flush. Add a real-rrweb test with a sampled-in old session and a sampled-out new session.

Prompt to fix with AI (copy-paste)
## Context
@packages/browser/src/extensions/replay/external/lazy-loaded-session-recorder.ts#L2016-2018

<issue_description>
Real rrweb re-enters `_updateWindowAndSessionIds` during `$session_id_change`. This new path replaces the IDs before `stop()` flushes the old buffer. `_flushBuffer()` then evaluates the new session's sampling and trigger state. A sampled-out or trigger-pending new session suppresses the flush. `stop()` then discards valid old-session data.
</issue_description>

<issue_validation>
- **Checked:** The flagged lines against the PR diff (`gh pr diff 4750`), plus `stop()`, `_flushBuffer()`, `_captureSnapshotBuffered()`, `_onSessionIdCallback()`, `get status`, `allMatchSessionRecordingStatus`/`anyMatchSessionRecordingStatus`, `V1RecordingStrategy.makeSamplingDecisions`/`ensureSamplingDecision`, and `sampleOnProperty`.
- **Found:** The mechanism is real. `lazy-loaded-session-recorder.ts:2030` assigns `this._windowId`/`this._sessionId`, then `:2038` calls `stop()`. `stop()` runs `_flushBuffer()` then `_clearBuffer()` (`:1334`). `_flushBuffer()` reads the new id: `ensureSamplingDecision(this.sessionId)` at `:1737` and `status` at `:1645` both use `this.sessionId`, and `_isSampled` (`:530`) decodes the decision against `this.sessionId`. A sampled-out session returns `DISABLED` (`triggerMatching.ts:671`, `:714`) and a pending trigger returns `BUFFERING` (`:666`, `:704`); both make `_flushBuffer` return the buffer un-drained (`:1740`), so the following `_clearBuffer()` drops it.
- **Found:** The buffer is non-empty at that moment. `$session_ending` is emitted at `:1188` before the re-entrant `$session_id_change` and is appended under the old id (lifecycle events skip `_updateWindowAndSessionIds`, `:1583`), so the discarded buffer contains real old-session data plus the session-linking marker.
- **Found:** The flagged ordering is NOT introduced by this PR. The diff touches only the guard at `:2016` (`if (this._isIdle)` → `if (this._isIdle === true)`); the assign-then-`stop()` sequence at `:2030`-`:2039` is unchanged, and it is already the mainstream path whenever `_isIdle === false` and a session rotates (for example `sessionPastMaximumLength` while the user is active). The PR only routes the `'unknown'` state into the same code.
- **Found:** The same trade-off is already deliberate elsewhere in this file: `_captureSnapshotBuffered` flushes on `sessionChanged` with the new id in place and explicitly discards a suppressed flush (`:1843`-`:1848`, with a comment stating why relabeling would mis-attribute).
- **Found:** The suggested fix is only partly effective on the path described. `_clearConditionalRecordingPersistence()` runs at `:1209`, before the re-entrant emit, and unregisters the trigger-activated and sampling keys, so an old-id flush would still read trigger-pending → `BUFFERING`. It does help the sampling case, because `sampleOnProperty` (`extensions/sampling.ts:24`) is a deterministic hash of the session id, so re-deciding for the old id reproduces the old decision.
- **Impact:** Confirmed data loss, but bounded. Change 3 in this same PR schedules the 2 s flush timer during `'unknown'` (`RECORDING_BUFFER_TIMEOUT = 2000`, `:120`), so the residual buffer at rotation is the last ≤2 s of old-session events plus `$session_ending` — not a whole recording. It bites only when sampling or triggers gate the new session.
- **Priority:** Lowered to `consider`. The defect is real and nameable, so it stays on record, but `must_fix` overstates it: the ordering is pre-existing untouched code shared with the already-reachable `_isIdle === false` rotation path, the loss is the tail of a session that ends anyway, and the codebase already accepts this discard at `:1843`. Reordering `stop()` changes rotation semantics for every idle state and needs its own tests, which is wider than this targeted fix for #4202.
</issue_validation>

## Task
Investigate the issue and solve it

<potential_solution>
Call `stop()` while the recorder still has the old IDs. Assign the new IDs after that flush. Add a real-rrweb test with a sampled-in old session and a sampled-out new session.
</potential_solution>

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.

2 participants