What is happening
With session.deferSessionRefresh: true, the client follows a GET /get-session response containing needsRefresh: true with POST /get-session. The refresh POST has no body and no Content-Type header.
In a Next.js Node route handler, the request is represented with a non-null but empty ReadableStream. better-call then applies the router-wide allowedMediaTypes: ["application/json"] check and returns 415 before Better Auth middleware or the session handler can run.
Minimal reproduction
const request = new Request("http://localhost:3000/api/auth/get-session", {
method: "POST",
body: new ReadableStream({
start(controller) {
controller.close();
},
}),
// Node's RequestInit extension
duplex: "half",
} as RequestInit & { duplex: "half" });
const response = await auth.handler(request);
console.log(response.status); // 415
The same handler succeeds when the request is sent as JSON:
const request = new Request("http://localhost:3000/api/auth/get-session", {
method: "POST",
headers: { "content-type": "application/json" },
body: "{}",
});
const response = await auth.handler(request);
console.log(response.status); // 200
Expected behavior
The deferred-refresh client POST should send a serialized JSON body and Content-Type: application/json (for example, body "{}"), so it satisfies the endpoint's media-type contract in Next.js/Vercel runtimes.
Versions checked
better-auth 1.6.24
better-auth 1.6.25
better-auth 1.7.0-rc.2
better-call 1.3.7
- Next.js 16.2.11
The relevant client path is the refresh POST in dist/client/session-atom.mjs. The failure occurs during Better Call context construction, so Better Auth hooks cannot normalize the request first.
What is happening
With
session.deferSessionRefresh: true, the client follows aGET /get-sessionresponse containingneedsRefresh: truewithPOST /get-session. The refresh POST has no body and noContent-Typeheader.In a Next.js Node route handler, the request is represented with a non-null but empty
ReadableStream.better-callthen applies the router-wideallowedMediaTypes: ["application/json"]check and returns 415 before Better Auth middleware or the session handler can run.Minimal reproduction
The same handler succeeds when the request is sent as JSON:
Expected behavior
The deferred-refresh client POST should send a serialized JSON body and
Content-Type: application/json(for example, body"{}"), so it satisfies the endpoint's media-type contract in Next.js/Vercel runtimes.Versions checked
better-auth1.6.24better-auth1.6.25better-auth1.7.0-rc.2better-call1.3.7The relevant client path is the refresh POST in
dist/client/session-atom.mjs. The failure occurs during Better Call context construction, so Better Auth hooks cannot normalize the request first.