Calling auth.api.getSession with next/headers and chunked cookies will fail with a JSON parsing error #2394

Closed
opened 2026-03-13 09:49:29 -05:00 by GiteaMirror · 2 comments
Owner

Originally created by @celestial-rose on GitHub (Nov 25, 2025).

[SOLVED] Update / Conclusion

Root Cause:
The SyntaxError and truncated session data were not caused by a bug in better-auth's chunking logic or Hono's setCookie loop. The issue was a Browser Security constraint regarding the Partitioned cookie attribute (CHIPS).

The Details:
I was setting partitioned: true in my cookie configuration while testing locally with secure: false (or over HTTP). Modern browsers strictly enforce that Partitioned cookies must be Secure.

  1. Because the environment was insecure, the browser silently rejected the Set-Cookie headers for the chunks.
  2. This made it appear as though Hono's loop was failing or that better-auth wasn't sending all headers.
  3. The API received incomplete/missing chunks, resulting in the JSON SyntaxError when trying to reassemble the session.

Resolution:
I confirmed that this setup works correctly in a production (HTTPS) environment where secure: true is set.

  • Fix: Ensure partitioned: true is only applied when secure: true.

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Have a large chunked cookie stored using cache cookieCache
  2. Call the auth api as follows (maybe the headers is not related to this error but this is my behavior)
import { headers } from "next/headers";

const session = await auth.api
       .getSession({
           headers: await headers(),
       })
  1. The API will fail with
SyntaxError: Unterminated string in JSON at position 2921 (line 1 column 2922)
[api]         at [object Object]
[api]         at safeJSONParse (file:///Users/[REDACTED]/node_modules/better-auth/dist/json-_HMgPUVh.mjs:17:15)
[api]         at null.<anonymous> (file:///Users/[REDACTED]/node_modules/better-auth/dist/session-BO-S7wVw.mjs:75:20)
[api]         at async internalHandler (file:///Users/[REDACTED]/node_modules/better-call/src/endpoint.ts:474:20)

and when console.logging within the dist better-auth/dist/json-_HMgPUVh.mjs:17:15 right before the JSON.parse; I can see that the session being retrieved is truncated and the JSON not full - which validates that the JSON is corrupted

Image

Current vs. Expected behavior

Current behavior is the failure of retrieving a cached cookie session had it been chunked.

What version of Better Auth are you using?

1.4.1

System info

{
  "system": {
    "platform": "darwin",
    "arch": "arm64",
    "version": "Darwin Kernel Version 24.6.0: Mon Aug 11 21:15:09 PDT 2025; root:xnu-11417.140.69.701.11~1/RELEASE_ARM64_T6041",
    "release": "24.6.0",
    "cpuCount": 16,
    "cpuModel": "Apple M4 Max",
    "totalMemory": "64.00 GB",
    "freeMemory": "1.45 GB"
  },
  "node": {
    "version": "v22.20.0",
    "env": "development"
  },
  "packageManager": {
    "name": "bun",
    "version": "1.2.22"
  },
  "frameworks": null,
  "databases": [
    {
      "name": "kysely",
      "version": "^0.27.6"
    }
  ],
  "betterAuth": {
    "version": "Unknown",
    "config": null
  }
}

Which area(s) are affected? (Select all that apply)

Backend

Auth config (if applicable)

import { betterAuth } from "better-auth"
export const auth = betterAuth({
    ...config,
    session: {
            cookieCache: {
                enabled: true,
                maxAge: 6 * 10 * 60, // Cache duration in seconds, 1 hour
            },
        },
});

Additional context

The chunk is happening because I am bringing the profileImage along with the OAuth data. Still not the reason for the bug, but easy to reproduce.
Pretty sure having all of better-auth's OAuth plugins default behavior should be to have this turned off anyway.

Originally created by @celestial-rose on GitHub (Nov 25, 2025). ### **[SOLVED] Update / Conclusion** **Root Cause:** The `SyntaxError` and truncated session data were not caused by a bug in `better-auth`'s chunking logic or Hono's `setCookie` loop. The issue was a **Browser Security constraint** regarding the `Partitioned` cookie attribute (CHIPS). **The Details:** I was setting `partitioned: true` in my cookie configuration while testing locally with `secure: false` (or over HTTP). Modern browsers strictly enforce that **Partitioned cookies must be Secure**. 1. Because the environment was insecure, the browser silently rejected the `Set-Cookie` headers for the chunks. 2. This made it appear as though Hono's loop was failing or that `better-auth` wasn't sending all headers. 3. The API received incomplete/missing chunks, resulting in the JSON `SyntaxError` when trying to reassemble the session. **Resolution:** I confirmed that this setup works correctly in a production (HTTPS) environment where `secure: true` is set. * **Fix:** Ensure `partitioned: true` is **only** applied when `secure: true`. ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. Have a large chunked cookie stored using cache cookieCache 2. Call the auth api as follows (maybe the headers is not related to this error but this is my behavior) ```ts import { headers } from "next/headers"; const session = await auth.api .getSession({ headers: await headers(), }) ``` 3. The API will fail with ``` SyntaxError: Unterminated string in JSON at position 2921 (line 1 column 2922) [api] at [object Object] [api] at safeJSONParse (file:///Users/[REDACTED]/node_modules/better-auth/dist/json-_HMgPUVh.mjs:17:15) [api] at null.<anonymous> (file:///Users/[REDACTED]/node_modules/better-auth/dist/session-BO-S7wVw.mjs:75:20) [api] at async internalHandler (file:///Users/[REDACTED]/node_modules/better-call/src/endpoint.ts:474:20) ``` and when console.logging within the dist `better-auth/dist/json-_HMgPUVh.mjs:17:15` right before the JSON.parse; I can see that the session being retrieved is truncated and the JSON not full - which validates that the JSON is corrupted <img width="600" height="483" alt="Image" src="https://github.com/user-attachments/assets/feef924f-f7bf-47e6-8252-a29059bd4de7" /> ### Current vs. Expected behavior Current behavior is the failure of retrieving a cached cookie session had it been chunked. ### What version of Better Auth are you using? 1.4.1 ### System info ```bash { "system": { "platform": "darwin", "arch": "arm64", "version": "Darwin Kernel Version 24.6.0: Mon Aug 11 21:15:09 PDT 2025; root:xnu-11417.140.69.701.11~1/RELEASE_ARM64_T6041", "release": "24.6.0", "cpuCount": 16, "cpuModel": "Apple M4 Max", "totalMemory": "64.00 GB", "freeMemory": "1.45 GB" }, "node": { "version": "v22.20.0", "env": "development" }, "packageManager": { "name": "bun", "version": "1.2.22" }, "frameworks": null, "databases": [ { "name": "kysely", "version": "^0.27.6" } ], "betterAuth": { "version": "Unknown", "config": null } } ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth" export const auth = betterAuth({ ...config, session: { cookieCache: { enabled: true, maxAge: 6 * 10 * 60, // Cache duration in seconds, 1 hour }, }, }); ``` ### Additional context The chunk is happening because I am bringing the profileImage along with the OAuth data. Still not the reason for the bug, but easy to reproduce. Pretty sure having all of better-auth's OAuth plugins default behavior should be to have this turned off anyway.
GiteaMirror added the nextjsbug labels 2026-03-13 09:49:29 -05:00
Author
Owner

@better-auth-agent[bot] commented on GitHub (Nov 25, 2025):

It looks like the error is happening because the JSON session data is being split into chunks that aren’t properly reassembled before parsing, which leads to truncated data. One workaround is to prevent storing non‐critical large data (like the profileImage) within the session payload so that the cookie isn’t so large. Alternatively, you could adjust your cookie settings or use a different cookie cache configuration to better handle large or chunked data. Could you let us know if you’re using the default cookieCache settings or if you’ve customized them? Tag @better-auth-agent if you would like an answer from the Agent.

DiagramDiscordGitHub

Diagram Join Star

@better-auth-agent[bot] commented on GitHub (Nov 25, 2025): It looks like the error is happening because the JSON session data is being split into chunks that aren’t properly reassembled before parsing, which leads to truncated data. One workaround is to prevent storing non‐critical large data (like the profileImage) within the session payload so that the cookie isn’t so large. Alternatively, you could adjust your cookie settings or use a different cookie cache configuration to better handle large or chunked data. Could you let us know if you’re using the default cookieCache settings or if you’ve customized them? Tag @better-auth-agent if you would like an answer from the Agent. <!-- bot:webhook reply v1 --> [Diagram](https://repodiagrams.s3.eu-north-1.amazonaws.com/better-auth_ultra_detailed_interactive.html) • [Discord](https://discord.gg/better-auth) • [GitHub](https://github.com/better-auth/better-auth) [![Diagram](https://img.shields.io/badge/Diagram-2b3137?style=flat-square)](https://repodiagrams.s3.eu-north-1.amazonaws.com/better-auth_ultra_detailed_interactive.html) [![Join](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&style=flat-square)](https://discord.gg/better-auth) [![Star](https://img.shields.io/badge/star-181717?logo=github&logoColor=white&style=flat-square)](https://github.com/better-auth/better-auth)
Author
Owner

@celestial-rose commented on GitHub (Nov 25, 2025):

In my cookies I only see a .0 and not .1, so maybe this is the issue ?
In setting the chunked cookie, and not necessarily in the retrieving
EDIT : after console.logging in the dist version of packages/better-auth/src/cookies/index.ts for the cookies values, I can see both cookies, though only one is being set, the first one. if I manually add the second one, the API works
EDIT2 : the culprit is createSessionStore.setCookies() which for chunked cookies fails to set both chunked cookies, only one. I can see the chunks, only one gets set. my first intuition was a non-resolved Promise, but ctx.setCookie is not async. This might be related to not supporting double Set-Cookie headers ? This feels like some Hono weirdness
EDIT3_FINAL : setting partitioned: true in the defaultCookieAttributes is the culprit, not sure why and why partitioned matters. I think the partitioned parameter somehow conflicts with the for loop on Hono's ctx.setCookie() or maybe it's only a local thing since secure is set to false while partitioned: true ?

@ping-maxwell After having deployed it in a secure environment, I can confirm that setting Partitioned to true but in a Secure environment is working correctly and no API is failing. Closing this; sorry for the mess (but learned a hell lot about better-auth's internals)

@celestial-rose commented on GitHub (Nov 25, 2025): In my cookies I only see a .0 and not .1, so maybe this is the issue ? In setting the chunked cookie, and not necessarily in the retrieving EDIT : after console.logging in the dist version of `packages/better-auth/src/cookies/index.ts` for the cookies values, I can see both cookies, though only one is being set, the first one. if I manually add the second one, the API works EDIT2 : the culprit is `createSessionStore.setCookies()` which for chunked cookies fails to set both chunked cookies, only one. I can see the chunks, only one gets set. my first intuition was a non-resolved Promise, but `ctx.setCookie` is not async. This might be related to not supporting double Set-Cookie headers ? This feels like some Hono weirdness EDIT3_FINAL : setting `partitioned: true` in the `defaultCookieAttributes` is the culprit, not sure why and why `partitioned` matters. I think the `partitioned` parameter somehow conflicts with the for loop on Hono's `ctx.setCookie()` or maybe it's only a local thing since `secure` is set to `false` while `partitioned: true` ? @ping-maxwell After having deployed it in a secure environment, I can confirm that setting `Partitioned` to true but in a Secure environment is working correctly and no API is failing. Closing this; sorry for the mess (but learned a hell lot about better-auth's internals)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#2394