[PR #9050] fix(oauth): prevent crash when APIError has empty message in databaseHooks #25302

Open
opened 2026-04-15 22:49:14 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/better-auth/better-auth/pull/9050
Author: @jaydeep-pipaliya
Created: 4/9/2026
Status: 🔄 Open

Base: mainHead: fix/oauth-apierror-empty-message-crash


📝 Commits (3)

  • 7473192 fix(oauth): prevent crash when APIError has empty message in databaseHooks
  • fd2b249 Merge branch 'main' into fix/oauth-apierror-empty-message-crash
  • 9483952 add changeset for oauth empty message fix

📊 Changes

3 files changed (+11 additions, -5 deletions)

View changed files

.changeset/fix-oauth-empty-message-crash.md (+5 -0)
📝 packages/better-auth/src/api/routes/callback.ts (+5 -4)
📝 packages/better-auth/src/oauth2/link-account.ts (+1 -1)

📄 Description

What does this PR do?

Fixes #8676

When an APIError is thrown in databaseHooks.user.create.before during OAuth social sign-in without a message property (e.g., relying on the i18n plugin to inject translation based on code), the server crashes with:

TypeError: null is not an object (evaluating 'session.session')
  at setSessionCookie

Root cause

The crash path:

1. databaseHooks.user.create.before throws new APIError("FORBIDDEN")  // no message, just code
2. createOAuthUser catches it in link-account.ts
3. Returns { error: e.message, data: null }    // e.message is "" (empty string)
4. callback.ts checks: if (result.error)       // "" is falsy → check passes through!
5. const { session, user } = result.data!      // result.data is null → CRASH

The core issue: APIError.message can be an empty string when the user omits the message parameter and relies on code for i18n translation. Empty string "" is falsy in JavaScript, so if (result.error) doesn't catch it.

Fix

link-account.ts — fallback chain for error message:

// Before
error: e.message,

// After  
error: e.message || e.body?.code || "unable to create user",

callback.ts — defense in depth, also check for missing data:

// Before
if (result.error) { ... }
const { session, user } = result.data!;

// After
if (result.error || !result.data) { ... }
const { session, user } = result.data;

Why both fixes?

  1. link-account.ts: Ensures handleOAuthUserInfo always returns a truthy error string so callers can rely on the error check
  2. callback.ts: Removes the unsafe ! non-null assertion and adds a !result.data guard — if any future code path returns { error: null, data: null }, the callback won't crash

Summary by cubic

Prevent crash on OAuth sign-in when APIError from databaseHooks.user.create.before has an empty message. Adds a safe error fallback and null-data guard to log/redirect instead of crashing.

  • Bug Fixes
    • packages/better-auth/src/oauth2/link-account.ts: fallback e.message || e.body?.code || "unable to create user"; add patch changeset for better-auth.
    • packages/better-auth/src/api/routes/callback.ts: handle !result.data, default "unable_to_create_user" for logging/redirect, remove non-null assert.

Written for commit 94839522e1. Summary will update on new commits.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/better-auth/better-auth/pull/9050 **Author:** [@jaydeep-pipaliya](https://github.com/jaydeep-pipaliya) **Created:** 4/9/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `fix/oauth-apierror-empty-message-crash` --- ### 📝 Commits (3) - [`7473192`](https://github.com/better-auth/better-auth/commit/7473192012c7b246c38059dbb10fbaea70c2287e) fix(oauth): prevent crash when APIError has empty message in databaseHooks - [`fd2b249`](https://github.com/better-auth/better-auth/commit/fd2b249eaf903e7903c8cf28e30a62251a516079) Merge branch 'main' into fix/oauth-apierror-empty-message-crash - [`9483952`](https://github.com/better-auth/better-auth/commit/94839522e1b98b7cae2f56feaae09a11a84936b9) add changeset for oauth empty message fix ### 📊 Changes **3 files changed** (+11 additions, -5 deletions) <details> <summary>View changed files</summary> ➕ `.changeset/fix-oauth-empty-message-crash.md` (+5 -0) 📝 `packages/better-auth/src/api/routes/callback.ts` (+5 -4) 📝 `packages/better-auth/src/oauth2/link-account.ts` (+1 -1) </details> ### 📄 Description ## What does this PR do? Fixes #8676 When an `APIError` is thrown in `databaseHooks.user.create.before` during OAuth social sign-in **without a `message` property** (e.g., relying on the i18n plugin to inject translation based on `code`), the server crashes with: ``` TypeError: null is not an object (evaluating 'session.session') at setSessionCookie ``` ## Root cause The crash path: ``` 1. databaseHooks.user.create.before throws new APIError("FORBIDDEN") // no message, just code 2. createOAuthUser catches it in link-account.ts 3. Returns { error: e.message, data: null } // e.message is "" (empty string) 4. callback.ts checks: if (result.error) // "" is falsy → check passes through! 5. const { session, user } = result.data! // result.data is null → CRASH ``` The core issue: `APIError.message` can be an empty string when the user omits the `message` parameter and relies on `code` for i18n translation. Empty string `""` is falsy in JavaScript, so `if (result.error)` doesn't catch it. ## Fix **`link-account.ts`** — fallback chain for error message: ```typescript // Before error: e.message, // After error: e.message || e.body?.code || "unable to create user", ``` **`callback.ts`** — defense in depth, also check for missing data: ```typescript // Before if (result.error) { ... } const { session, user } = result.data!; // After if (result.error || !result.data) { ... } const { session, user } = result.data; ``` ## Why both fixes? 1. **`link-account.ts`**: Ensures `handleOAuthUserInfo` always returns a truthy error string so callers can rely on the error check 2. **`callback.ts`**: Removes the unsafe `!` non-null assertion and adds a `!result.data` guard — if any future code path returns `{ error: null, data: null }`, the callback won't crash <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Prevent crash on OAuth sign-in when `APIError` from `databaseHooks.user.create.before` has an empty message. Adds a safe error fallback and null-data guard to log/redirect instead of crashing. - **Bug Fixes** - `packages/better-auth/src/oauth2/link-account.ts`: fallback `e.message || e.body?.code || "unable to create user"`; add patch changeset for `better-auth`. - `packages/better-auth/src/api/routes/callback.ts`: handle `!result.data`, default `"unable_to_create_user"` for logging/redirect, remove non-null assert. <sup>Written for commit 94839522e1b98b7cae2f56feaae09a11a84936b9. Summary will update on new commits.</sup> <!-- End of auto-generated description by cubic. --> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-04-15 22:49:15 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#25302