Skip to content

fix: txn cookie accumulation#2748

Open
Piyush-85 wants to merge 9 commits into
mainfrom
fix/txn-accumulation
Open

fix: txn cookie accumulation#2748
Piyush-85 wants to merge 9 commits into
mainfrom
fix/txn-accumulation

Conversation

@Piyush-85

@Piyush-85 Piyush-85 commented Jul 13, 2026

Copy link
Copy Markdown
Contributor
  • All new/changed/fixed functionality is covered by tests (or N/A)
  • I have added documentation for all new/changed functionality (or N/A)

📋 Changes

Fixes unbounded _txn* transaction-cookie accumulation that produces 431 Request Header Fields Too Large, and adds a warning for the other main cause of oversized request headers - a large session cookie.

  1. Prefetch guard - stop creating transaction cookies for flows that never complete
  • handler() now returns 401 (empty body) on GET /auth/login when the request is a known Next.js prefetch, instead of running handleLogin and writing a txn cookie that will never be consumed.
  • Detection is via a new exported helper isNonNavigationalRequest(req) (src/utils/request.ts), which matches explicit prefetch headers only: next-router-prefetch, purpose: prefetch, sec-purpose: prefetch, x-middleware-prefetch, and accept: text/x-component. It intentionally does not key off sec-fetch-mode, to avoid blocking legitimate fetch()/XHR calls to /auth/login.
  1. Bounded, FIFO eviction of transaction cookies
  • Transaction cookie values are now encoded as {ts}:{jwe} (unix-seconds creation timestamp prefix). This enables O(1) oldest-first ordering during eviction with no decryption and no cookie-name change.
  • On save(), when the combined size of all _txn* cookies exceeds 3500kb, the oldest are evicted (FIFO) until back under the limit, before the new cookie is written. The cookie being (re)written for the current state is never evicted.
  • Backward compatible reads: get() strips the {ts}: prefix before decrypting; legacy bare {jwe} values (no prefix) are still decrypted, and are treated as timestamp 0 (evicted first) during cleanup.
  • Callback cleanup delete removes only the completing flow's txn{state}, preserving in-flight logins in other tabs (multi-tab safe).
  1. Session-cookie size warning (new)
  • StatelessSessionStore.set() now console.warns when the total encoded size of the _session chunks reaches SESSION_COOKIE_SIZE_WARN_BYTES (4096 bytes), advising the developer to remove unnecessary custom claims or switch to a stateful session.
  • Why: unlike transaction cookies, the session is never evicted, so a large session is the primary remaining cause of 431. Previously the session cookie had no size check at all, the existing 4096-byte check in storeInCookie only ever ran for connection-token (_FC*) cookies, and its sessionCookieName branch was unreachable dead code (now removed).
  • This is diagnostic only (a warning); it changes no cookie-writing behavior and makes no assumption about the platform header limit.

Docs (EXAMPLES.md + README.md)

  • Consolidated all 431 guidance under one section, renamed to "Preventing '431 Request Header Fields Too Large' Errors", and added it to the table of contents. It documents the prefetch 401 guard, the fixed-limit FIFO eviction, the two recommended practices
    - use <a>/<Link prefetch={false}> — not <Link href="/auth/login">
    - prefer withPageAuthRequired over middleware redirects
    - recommends lowering transactionCookie.maxAge if in-flight logins are being evicted too aggressively.

📎 References

🎯 Testing

  • src/server/txn-cookie-accumulation.test.ts — prefetch-header detection (positive/negative), 401 + no cookie written on prefetch, real navigation allowed through, FIFO eviction at the fixed 3500-byte limit, oldest-first ordering incl. legacy timestamp=0 values, prefix-scoped eviction, {ts}:{jwe} encoding/decoding round-trip, callback deletes only the completing cookie (multi-tab preserved), and a @ts-expect-error guard proving maxSizeBytes is nolonger an accepted option.
  • src/server/session/stateless-session-store.test.ts — warns on an oversized (multi-chunk) session, does not warn on a normal session.
  • src/server/transaction-store.test.ts, redundant-txn-cookie-deletion.test.ts, auth-client.test.ts, mfa-popup.test.ts updated for the value-format and eviction changes.

Summary by CodeRabbit

  • Bug Fixes
    • Prevented transaction-cookie writes for Next.js prefetch/non-navigational login requests (early 401), reducing “431 Request Header Fields Too Large” errors.
    • Added transaction-cookie size protection with FIFO eviction (including legacy compatibility) and improved single-transaction retry/callback cleanup to only delete the completing flow’s cookie.
    • Added warnings for oversized session cookies.
  • New Features
    • Added request detection utility to distinguish prefetch-style requests.
  • Documentation
    • Updated README/EXAMPLES with safe login link guidance and a new “Preventing ‘431…’ Errors” section.
  • Tests
    • Updated cookie decoding in transaction-related test suites to handle the stored value prefix.

@Piyush-85
Piyush-85 requested a review from a team as a code owner July 13, 2026 15:04
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 11b5082f-5be9-48a9-89f9-449bb1438883

📥 Commits

Reviewing files that changed from the base of the PR and between b083a04 and 73c819d.

📒 Files selected for processing (4)
  • README.md
  • src/server/transaction-store.ts
  • src/server/txn-cookie-accumulation.test.ts
  • src/utils/request.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/utils/request.ts
  • README.md
  • src/server/txn-cookie-accumulation.test.ts
  • src/server/transaction-store.ts

📝 Walkthrough

Walkthrough

The PR blocks transaction creation from Next.js prefetches, evicts accumulated transaction cookies, adds cookie-size warnings, updates transaction-cookie encoding and tests, forwards client options, and documents practices for avoiding 431 errors.

Changes

Transaction Cookie Controls

Layer / File(s) Summary
Prefetch login flow
src/utils/request.ts, src/server/auth-client.ts, src/server/txn-cookie-accumulation.test.ts
Non-navigational login requests return 401 without writing transaction cookies; navigational flows pass request cookies to transaction persistence and verify callback cleanup.
Transaction cookie storage
src/server/transaction-store.ts, src/server/*test.ts, src/test/utils.ts
Transaction cookies use timestamp-prefixed values, FIFO eviction under a 3500-byte limit, legacy-value handling, single-transaction overwrites, and updated decryption assertions.
Cookie size warnings
src/server/session/stateless-session-store.ts, src/server/session/stateless-session-store.test.ts
Session-cookie chunks are measured collectively and warnings are emitted at the 4096-byte threshold.
Client option wiring
src/server/client.ts
The AuthClientProvider forwards custom fetch, MFA token TTL, and CSP nonce options.
Documentation guidance
README.md, EXAMPLES.md
Login prefetch restrictions, page-protection recommendations, transaction-cookie options, and 431-error prevention behavior are documented.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related issues

  • auth0/nextjs-auth0#2450 — Addresses transaction-cookie accumulation and 431 failures through prefetch prevention and FIFO eviction.

Possibly related PRs

  • auth0/nextjs-auth0#2670 — Both changes update passwordless transaction-cookie persistence through TransactionStore.

Suggested reviewers: tusharpandey13

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The AuthClientProvider option forwarding in src/server/client.ts is unrelated to #1917 and appears outside the cookie-accumulation fix. Split the provider-wiring option forwarding into a separate PR or explain why it is needed for the cookie-accumulation fix.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and directly describes the main fix: transaction-cookie accumulation.
Linked Issues check ✅ Passed The PR matches #1917 by preventing prefetch cookies, bounding transaction-cookie growth, and cleaning up only the completed flow's cookie.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/txn-accumulation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov-commenter

codecov-commenter commented Jul 13, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.39130% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.32%. Comparing base (652f41a) to head (73c819d).

Files with missing lines Patch % Lines
src/server/session/stateless-session-store.ts 85.71% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2748      +/-   ##
==========================================
+ Coverage   88.11%   88.32%   +0.21%     
==========================================
  Files          79       79              
  Lines       11105    11191      +86     
  Branches     2296     2320      +24     
==========================================
+ Hits         9785     9885     +100     
+ Misses       1276     1262      -14     
  Partials       44       44              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai 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.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@EXAMPLES.md`:
- Around line 4048-4051: The transaction-cookie eviction check must include the
incoming cookie size: update the logic calculating txnBytes or the cap condition
to evaluate existing transaction-cookie bytes plus newCookieValue’s serialized
size against the 3500-byte limit. Preserve FIFO eviction and leave
non-transaction cookies untouched, and add a boundary test covering a new cookie
that causes the combined total to reach or exceed the limit.

In `@README.md`:
- Around line 193-194: Align the login-link guidance in README.md with the
corresponding recommendation in EXAMPLES.md. Choose one tested approach—prefer
plain <a> links until the RSC-navigation detector is fixed, or consistently
document Link with prefetch disabled—and update the conflicting documentation so
both files prescribe the same behavior.

In `@src/utils/request.ts`:
- Around line 27-35: The isNonNavigationalRequest function incorrectly treats
the generic Accept header as a prefetch signal. Remove that check or require an
explicit prefetch indicator, then update the login snippets in EXAMPLES.md at
lines 237-238 and 4057-4068 to reflect the corrected navigation behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7a92bef5-5000-46b6-8039-d5704cdc15da

📥 Commits

Reviewing files that changed from the base of the PR and between 17bdeda and 1df8c4f.

📒 Files selected for processing (13)
  • EXAMPLES.md
  • README.md
  • src/server/auth-client.test.ts
  • src/server/auth-client.ts
  • src/server/client.ts
  • src/server/mfa-popup.test.ts
  • src/server/session/stateless-session-store.test.ts
  • src/server/session/stateless-session-store.ts
  • src/server/transaction-store.test.ts
  • src/server/transaction-store.ts
  • src/server/txn-cookie-accumulation.test.ts
  • src/test/utils.ts
  • src/utils/request.ts
💤 Files with no reviewable changes (1)
  • src/server/client.ts

Comment thread EXAMPLES.md
Comment thread README.md Outdated
Comment thread src/utils/request.ts
@Piyush-85 Piyush-85 changed the title fix txn cookie accumulation fix: txn cookie accumulation Jul 15, 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.

v4: Infinitely stacking cookies

2 participants