[GH-ISSUE #8576] deleteSessionCookie does not work in createAuthEndpoint on APIError thrown #28447

Open
opened 2026-04-17 19:53:47 -05:00 by GiteaMirror · 1 comment
Owner

Originally created by @stychu on GitHub (Mar 12, 2026).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/8576

You've hit a known bug (#7473) — when you throw an APIError, Better Auth's error handling replaces all previously set response headers, including any Set-Cookie headers from deleteSessionCookie. So the cookie deletion is silently discarded.

Your workaround of manually constructing the headers and passing them to APIError is the right approach. The issue is that deleteSessionCookie returns void and operates entirely through side effects on the context.

Your suggestion is solid — if deleteSessionCookie returned the Set-Cookie headers instead of (or in addition to) setting them via ctx.setCookie, you could:

  1. Use it normally in success paths (headers get applied)
  2. Capture the headers and pass them to APIError in error paths

One alternative workaround until that's fixed: return a successful response with an error status code instead of throwing:

await deleteSessionCookie(ctx);
return ctx.json(
  { error: "Unable to get idToken — authentication required" },
  { status: 401 }
);

But this changes the API contract and may not work for your use case. Your feature request for deleteSessionCookie to return headers would be a great contribution to make stateless mode more robust.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

Originally posted by @dosubot in https://github.com/better-auth/better-auth/discussions/8287#discussioncomment-16101534

Originally created by @stychu on GitHub (Mar 12, 2026). Original GitHub issue: https://github.com/better-auth/better-auth/issues/8576 <!-- Answer --> You've hit a [known bug (#7473)](https://github.com/better-auth/better-auth/issues/7473) — when you throw an `APIError`, Better Auth's error handling **replaces all previously set response headers**, including any `Set-Cookie` headers from `deleteSessionCookie`. So the cookie deletion is silently discarded. Your workaround of manually constructing the headers and passing them to `APIError` is the right approach. The issue is that [`deleteSessionCookie` returns `void`](https://github.com/better-auth/better-auth/blob/db5a44424f5747c47a7da347613e42b664e1e734/packages/better-auth/src/cookies/index.ts#L321-L357) and operates entirely through side effects on the context. Your suggestion is solid — if `deleteSessionCookie` returned the `Set-Cookie` headers instead of (or in addition to) setting them via `ctx.setCookie`, you could: 1. Use it normally in success paths (headers get applied) 2. Capture the headers and pass them to `APIError` in error paths One alternative workaround until that's fixed: return a successful response with an error status code instead of throwing: ```ts await deleteSessionCookie(ctx); return ctx.json( { error: "Unable to get idToken — authentication required" }, { status: 401 } ); ``` But this changes the API contract and may not work for your use case. Your feature request for `deleteSessionCookie` to return headers would be a great contribution to make stateless mode more robust. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot?utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=brand-link).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/2ca0091f-a211-4507-bcfd-709f63b98459?feedback_type=great_response&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/2ca0091f-a211-4507-bcfd-709f63b98459?feedback_type=irrelevant_answer&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/2ca0091f-a211-4507-bcfd-709f63b98459?feedback_type=incorrect_sources&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/2ca0091f-a211-4507-bcfd-709f63b98459?feedback_type=too_verbose&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/2ca0091f-a211-4507-bcfd-709f63b98459?feedback_type=hallucination&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/2ca0091f-a211-4507-bcfd-709f63b98459?feedback_type=bug_report&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-bug_report) | [Other](https://app.dosu.dev/response-feedback/2ca0091f-a211-4507-bcfd-709f63b98459?feedback_type=other&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=chat-badge)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=You%27ve%20hit%20a%20%5Bknown%20bug%20%28%237473%29%5D%28https%3A//github.com/better-auth/better-auth/issues/7473%29%20%E2%80%94%20when%20you%20throw%20an%20%60APIError%60%2C%20Better%20Auth%27s%20error%20handling%20%2A%2Areplaces%20all%20previously%20set%20response%20headers%2A%2A%2C%20including%20any%20%60Set-Cookie%60%20headers%20from%20%60deleteSessionCookie%60.%20So%20the%20cookie%20deletion%20is%20silently%20discarded.%0A%0AYour%20workaround%20of%20manually%20constructing%20the%20headers%20and%20passing%20them%20to%20%60APIError%60%20is%20the%20right%20approach.%20The%20issue%20is%20that%20%5B%60deleteSessionCookie%60%20returns%20%60void%60%5D%28https%3A//github.com/better-auth/better-auth/blob/db5a44424f5747c47a7da347613e42b664e1e734/packages/better-auth/src/cookies/index.ts%23L321-L357%29%20and%20operates%20entirely%20through%20side%20effects%20on%20the%20context.%0A%0AYour%20suggestion%20is%20solid%20%E2%80%94%20if%20%60deleteSessionCookie%60%20returned%20the%20%60Set-Cookie%60%20headers%20instead%20of%20%28or%20in%20addition%20to%29%20setting%20them%20via%20%60ctx.setCookie%60%2C%20you%20could%3A%0A1.%20Use%20it%20normally%20in%20success%20paths%20%28headers%20get%20applied%29%0A2.%20Capture%20the%20headers%20and%20pass%20them%20to%20%60APIError%60%20in%20error%20paths%0A%0AOne%20alternative%20workaround%20until%20that%27s%20fixed%3A%20return%20a%20successful%20response%20with%20an%20error%20status%20code%20instead%20of%20throwing%3A%0A%0A%60%60%60ts%0Aawait%20deleteSessionCookie%28ctx%29%3B%0Areturn%20ctx.json%28%0A%20%20%7B%20error%3A%20%22Unable%20to%20get%20idToken%20%E2%80%94%20authentication%20required%22%20%7D%2C%0A%20%20%7B%20status%3A%20401%20%7D%0A%29%3B%0A%60%60%60%0A%0ABut%20this%20changes%20the%20API%20contract%20and%20may%20not%20work%20for%20your%20use%20case.%20Your%20feature%20request%20for%20%60deleteSessionCookie%60%20to%20return%20headers%20would%20be%20a%20great%20contribution%20to%20make%20stateless%20mode%20more%20robust.)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot?utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=join-discord)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/discussions/8287) _Originally posted by @dosubot in https://github.com/better-auth/better-auth/discussions/8287#discussioncomment-16101534_
GiteaMirror added the corebug labels 2026-04-17 19:53:48 -05:00
Author
Owner

@stewartjarod commented on GitHub (Apr 16, 2026):

Opened #9211 to fix this. The root cause was that thrown APIErrors dropped any headers already set on ctx (including the Set-Cookie from deleteSessionCookie); the PR attaches ctx.responseHeaders to the error so toAuthEndpoints can merge them into the final response, matching how the after-hooks catch already handles it.

<!-- gh-comment-id:4260856156 --> @stewartjarod commented on GitHub (Apr 16, 2026): Opened #9211 to fix this. The root cause was that thrown `APIError`s dropped any headers already set on `ctx` (including the `Set-Cookie` from `deleteSessionCookie`); the PR attaches `ctx.responseHeaders` to the error so `toAuthEndpoints` can merge them into the final response, matching how the after-hooks catch already handles it.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#28447