Skip to content

fix: prune stale sessionData_* cookies and stop noisy parse log#554

Open
Vadman97 wants to merge 1 commit into
mainfrom
vkorolik/prune-session-cookies
Open

fix: prune stale sessionData_* cookies and stop noisy parse log#554
Vadman97 wants to merge 1 commit into
mainfrom
vkorolik/prune-session-cookies

Conversation

@Vadman97
Copy link
Copy Markdown
Contributor

@Vadman97 Vadman97 commented May 13, 2026

Summary

A customer reported their cookies were full of session* keys to the point where some services rejected API calls due to overly long context headers.

Root cause: setItem writes session data to both localStorage and cookies, but pruneSessionData only walked localStorage. Whenever the two stores drifted (cleared site data, subdomain mismatch, parallel tabs, localStorage temporarily unavailable when written), sessionData_* cookies accumulated indefinitely and bloated the Cookie header until unrelated APIs started rejecting requests.

Also fixes a noisy error-level "failed to parse session data for key sessionData_..." log (the successor to the older "is not session data" log removed in #269). It fired on every page load whenever a cookie was truncated past the 4KB limit — exactly the bloat scenario.

Changes

  • pruneSessionData now walks both getPersistentStorage() and cookieStorage.keys() and removes stale entries from whichever store holds them.
  • Fall back to sessionStartTime when lastPushTime is absent, so sessions that ended before their first push still age out (previously they were pinned forever).
  • Treat entries with no usable timestamp or corrupt JSON as stale and remove silently — no more error logs on truncated cookies.
  • Added CookieStorage.keys() for enumerating cookies via js-cookie.
  • New test suite covers cookie-only stale data, truncated cookies, missing-timestamp entries, sessionStartTime fallback, and parallel-tab retention.

Test plan

  • yarn run vitest run — 426 tests pass (existing 421 + 5 new)
  • yarn format-check clean
  • yarn turbo run enforce-size --filter highlight.run — 166.2 KB / 256 KB
  • Verify in a staging app with several active sessions that older sessionData_* cookies are removed when a new session starts

🤖 Generated with Claude Code

setItem writes session data to both localStorage and cookies, but
pruneSessionData only walked localStorage. As a result, sessionData_*
cookies accumulated indefinitely whenever localStorage and cookies
fell out of sync (cleared site data, subdomain mismatch, parallel
tabs, etc.), eventually bloating the Cookie header enough to break
unrelated API calls.

Walk cookies too, fall back to sessionStartTime so sessions that
ended before the first push still age out, and drop entries with no
usable timestamp. The error-level "failed to parse session data"
log fired on every page load when a cookie was truncated past 4KB —
exactly the bloat scenario — so silently remove corrupt entries
instead.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Vadman97 Vadman97 requested a review from a team as a code owner May 13, 2026 16:13
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default mode and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 04514c3. Configure here.

for (const key of candidates) {
let stale = true
try {
const sessionData = JSON.parse(getItem(key) || '{}') as SessionData
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cookie-only entries always treated as stale due to localStorage-only read

Medium Severity

The freshness check uses getItem(key) which only reads from getPersistentStorage() (localStorage), never from cookies. For entries discovered via cookieStorage.keys() that have no matching localStorage entry — the exact scenario this PR targets — getItem returns '', producing JSON.parse('{}') with no timestamps, so ts is always undefined and stale is always true. This means all cookie-only entries are unconditionally removed regardless of whether they contain fresh session data for an active parallel tab. The freshness check needs to fall back to cookieStorage.getItem(key) when getItem(key) returns empty.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 04514c3. Configure here.

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