fix(replay): stop mid-load unmounts breaking embedded recordings lists - #81597
fix(replay): stop mid-load unmounts breaking embedded recordings lists#81597mp-hog wants to merge 3 commits into
Conversation
loadSessionRecordings read values.filters after the API await resumed but before its breakpoint() guard, so embedded playlists (experiment recordings tab, vision scanner runs) that unmounted mid-request threw "[KEA] Can not find path" and dispatched a spurious failure. Move the breakpoint above the values reads; kea bumps breakpoint counters on beforeUnmount, so the resumed listener now aborts silently. Generated-By: PostHog Desktop Task-Id: 03c64c82-7dfc-4d5f-8fed-3d5de52245f5
|
Merging to
After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here |
🤖 CI report✅ Bundle size — 🟢 -2.1 KiB (-0.0%)Uncompressed size of every built Total: 67.75 MiB · 🟢 -2.1 KiB (-0.0%)
Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report ✅ Eager graph — within budgetHow much code each root ships on the eager path — downloaded and parsed before the surface is interactive. Measured from the esbuild output chunks (post-tree-shake, static imports only); lazy
🟢 Largest files eagerly shipped from
|
| Size | File |
|---|---|
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 24.6 KiB | ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js |
| 6.3 KiB | ../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js |
| 4.5 KiB | ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js |
| 3.9 KiB | ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js |
| 1.4 KiB | ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js |
| 1.3 KiB | src/RootErrorBoundary.tsx |
| 912 B | ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js |
| 789 B | src/scenes/ChunkLoadErrorBoundary.tsx |
| 762 B | src/index.tsx |
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
| Size | File |
|---|---|
| 285.3 KiB | ../node_modules/.pnpm/posthog-js@1.410.1/node_modules/posthog-js/dist/rrweb.js |
| 267.7 KiB | ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 238.4 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 231.5 KiB | ../node_modules/.pnpm/posthog-js@1.410.1/node_modules/posthog-js/dist/module.js |
| 154.3 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 105.2 KiB | src/lib/api.ts |
| 94.6 KiB | ../packages/quill/packages/quill/dist/index.js |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 90.6 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479
✅ Toolbar bundle — eager 2.20 MiB within budget
What the toolbar ships to customer pages, measured from the esbuild output (minified, post-tree-shake). The eager set is the entry plus everything statically imported from it — fetched before any feature runs; deferred chunks load lazily. The eager guardrail is 5.72 MiB. Each output file must also stay below 10 MB, where CloudFront stops compressing it. The module boundary is enforced separately by check-toolbar-graph.
| Metric | Size | Δ vs base | Budget |
|---|---|---|---|
| Eager (shipped) entry + static imports |
2.20 MiB · 17 files | 🔺 +3.8 KiB (+0.2%) | ████░░░░░░ 38.5% of 5.72 MiB |
| Deferred (lazy) | 2.08 MiB · 33 files | 🟢 -15 B (-0.0%) | n/a — loads on demand |
Loader dist/toolbar.js |
1.1 KiB | no change | █░░░░░░░░░ 5.8% of 19.5 KiB |
Largest eagerly-shipped chunks
| Size | File |
|---|---|
| 729.2 KiB | dist/toolbar/toolbar-app-KABLUAZC.css |
| 553.0 KiB | dist/toolbar/chunk-chunk-CAJJBQHG.js |
| 484.6 KiB | dist/toolbar/chunk-chunk-UCWKK2W2.js |
| 133.6 KiB | dist/toolbar/chunk-chunk-RRH6FYIR.js |
| 131.8 KiB | dist/toolbar/chunk-chunk-T5KY5WYR.js |
| 71.2 KiB | dist/toolbar/toolbar-app-XRBEOWR6.js |
| 69.0 KiB | dist/toolbar/chunk-chunk-27JL52RE.js |
| 35.6 KiB | dist/toolbar/chunk-chunk-YBL2LK2H.js |
| 20.9 KiB | dist/toolbar/chunk-chunk-QGUDWYKZ.js |
| 12.2 KiB | dist/toolbar/chunk-chunk-PIK3PADE.js |
Posted automatically by check-toolbar-size · sizes are toolbar output bytes (shipped, post-tree-shake) from the esbuild metafile
✅ Dist folder size — 🔺 +7.55 MiB (+0.5%)
Total size of the built frontend/dist folder (all assets), compared against the base branch.
Total: 1429.02 MiB · 🔺 +7.55 MiB (+0.5%)
The `as ReturnType<typeof api.recordings.list>` cast contextually typed the Promise constructor, so its resolve callback no longer matched the `(value: unknown) => void` holder under strict function types (TS2322, caught by CI's Frontend typechecking). Build the promise untyped and cast only at the mock's return position. Generated-By: PostHog Desktop Task-Id: 03c64c82-7dfc-4d5f-8fed-3d5de52245f5
Capture values.filters before the awaits and report the fetch from the captured value, restoring breakpoint() to after the report. Superseded and abandoned fetches keep counting toward the list load-time metrics (no survivorship bias toward fast responses), and the report now carries the filters the request was built from rather than whatever they are when the response lands. Unmount safety is unchanged: the only post-await `values` reads sit behind the breakpoint, and dispatching an action on an unmounted logic is safe — only `values` reads throw. Adds a regression test that fails both if the report goes back to reading live values and if breakpoint() moves back above the report. Generated-By: PostHog Desktop Task-Id: 139ec0b8-42da-4ec0-b68d-d0a0e238992e
🦔 Hogbox preview · ✅ ready▶ Open the preview
commit |
|
Reviews (1): Last reviewed commit: "fix(replay): keep fetch reporting for su..." | Re-trigger Greptile |
Problem
Leaving an embedded recordings list while it is still loading throws a KEA store error, and later visits can find the list stuck on "Loading recordings…". The experiment Recordings tab hits this hardest: users open the tab, click away mid-load, and it comes back blank.
loadSessionRecordingsreadsvalues.filtersafterawait api.recordings.list(...)resumes, to report fetch analytics.valueson an unmounted keyed logic throws[KEA] Can not find path "…" in the store, which kea-loaders turns into a spuriousloadSessionRecordingsFailure.breakpoint()— the bail-out kea arms on unmount — sits below that read, so it never gets to stop the listener.Error tracking shows keyed variants of this daily, rising since the
experiment-recordings-tabrollout put more embedded lists in front of users: experiment tabs and bare keys, vision scanner runs.Complements #78247, which guards component-side bare reads of this logic. This PR guards the loader's own async resume.
Changes
loadSessionRecordingscapturesvalues.filtersonce, before any await, and reports fetch analytics from the captured value. Actions are safe to dispatch after unmount; onlyvaluesreads throw.breakpoint()stays after the report, still guarding the post-awaitvaluesreads in the return value.breakpoint()above the report. That drops superseded and abandoned fetches — the slow tail — fromreplay_list_load_ms, skewing the latency histogram toward fast responses.How did you test this code?
api.recordings.liston a controlled promise, unmounts, resolves. Fails before (KEA store error → failure action); passes now.breakpoint()moves above the report.pnpm --filter=@posthog/frontend fix— clean.typescript:checkreports only pre-existing errors from the unbuilt local@posthog/quillworkspace, none in changed files; CI is the authority.Automatic notifications
Docs update
None.
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
beforeUnmountbumps every listener breakpoint counter, kea-loaders swallows breakpoint throws, and built-logic action dispatches have no mount check.databaseTableListLogic(isMounted()guards),dataNodeLogic(AbortController+ breakpoints).Created with PostHog Desktop