[GH-ISSUE #5518] onAPIError.errorURL is ignored in OAuth callback flow #18905

Closed
opened 2026-04-15 17:36:10 -05:00 by GiteaMirror · 6 comments
Owner

Originally created by @noze12 on GitHub (Oct 23, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/5518

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Configure better-auth with onAPIError.errorURL:
export const auth = betterAuth({
  database: prismaAdapter(prisma, { provider: "postgresql" }),
  plugins: [nextCookies()],
  socialProviders: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    },
  },
  onAPIError: {
    errorURL: "/login",  // This is ignored
  },
  databaseHooks: {
    user: {
      create: {
        before: async (user) => {
          // Simulate validation failure
          throw new APIError("UNAUTHORIZED", {
            message: "User not authorized",
          });
        },
      },
    },
  },
});
  1. Call signInSocial:
await auth.api.signInSocial({
  body: {
    provider: "google",
  },
});
  1. Complete OAuth flow with Google

Current vs. Expected behavior

Expected

Users should be redirected to /login?error=User_not_authorized (the URL specified in onAPIError.errorURL) when an error occurs during user creation.

Actual

Users are redirected to /api/auth/error?error=User_not_authorized.

What version of Better Auth are you using?

1.3.27

System info

{
  "system": {
    "platform": "darwin",
    "arch": "arm64",
    "version": "Darwin Kernel Version 24.6.0: Mon Jul 14 11:29:54 PDT 2025; root:xnu-11417.140.69~1/RELEASE_ARM64_T8122",
    "release": "24.6.0",
    "cpuCount": 8,
    "cpuModel": "Apple M3",
    "totalMemory": "16.00 GB",
    "freeMemory": "0.35 GB"
  },
  "node": {
    "version": "v22.20.0",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "11.6.1"
  },
  "frameworks": null,
  "databases": null,
  "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({
  emailAndPassword: {  
    enabled: true
  },
});

Additional context

When I call signInSocial with errorCallbackURL, redirected to errorCallbackURL.

Maybe this code should respect onAPIError.errorURL:

if (!parsedData.errorURL) {
-  parsedData.errorURL = `${c.context.baseURL}/error`;
+  parsedData.errorURL = c.context.options.onAPIError?.errorURL || `${c.context.baseURL}/error`;
}
Originally created by @noze12 on GitHub (Oct 23, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/5518 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. Configure better-auth with `onAPIError.errorURL`: ```ts export const auth = betterAuth({ database: prismaAdapter(prisma, { provider: "postgresql" }), plugins: [nextCookies()], socialProviders: { google: { clientId: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET, }, }, onAPIError: { errorURL: "/login", // This is ignored }, databaseHooks: { user: { create: { before: async (user) => { // Simulate validation failure throw new APIError("UNAUTHORIZED", { message: "User not authorized", }); }, }, }, }, }); ``` 2. Call `signInSocial`: ```typescript await auth.api.signInSocial({ body: { provider: "google", }, }); ``` 3. Complete OAuth flow with Google ### Current vs. Expected behavior ## Expected Users should be redirected to `/login?error=User_not_authorized` (the URL specified in `onAPIError.errorURL`) when an error occurs during user creation. ## Actual Users are redirected to `/api/auth/error?error=User_not_authorized`. ### What version of Better Auth are you using? 1.3.27 ### System info ```bash { "system": { "platform": "darwin", "arch": "arm64", "version": "Darwin Kernel Version 24.6.0: Mon Jul 14 11:29:54 PDT 2025; root:xnu-11417.140.69~1/RELEASE_ARM64_T8122", "release": "24.6.0", "cpuCount": 8, "cpuModel": "Apple M3", "totalMemory": "16.00 GB", "freeMemory": "0.35 GB" }, "node": { "version": "v22.20.0", "env": "development" }, "packageManager": { "name": "npm", "version": "11.6.1" }, "frameworks": null, "databases": null, "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({ emailAndPassword: { enabled: true }, }); ``` ### Additional context When I call signInSocial with errorCallbackURL, redirected to errorCallbackURL. Maybe [this code](https://github.com/better-auth/better-auth/blob/v1.3.27/packages/better-auth/src/oauth2/state.ts#L96-L98) should respect onAPIError.errorURL: ```diff if (!parsedData.errorURL) { - parsedData.errorURL = `${c.context.baseURL}/error`; + parsedData.errorURL = c.context.options.onAPIError?.errorURL || `${c.context.baseURL}/error`; } ```
GiteaMirror added the lockedbug labels 2026-04-15 17:36:10 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Oct 23, 2025):

Hi @noze12! I'm Dosu and I’m helping the better-auth team.

You're correct—Better Auth v1.3.27 does not consistently respect onAPIError.errorURL in the OAuth callback flow. The code in state.ts hardcodes the error redirect to ${c.context.baseURL}/error if parsedData.errorURL is missing, ignoring your config. Your suggested patch to use c.context.options.onAPIError?.errorURL || ... would fix this and unify error handling with other parts of the codebase source.

This limitation is well-known and discussed in several issues (example), with workarounds like setting a global errorURL or using middleware to intercept /api/auth/error and redirect to your custom page. There is an open PR to centralize and improve error URL handling, including support for custom error URLs via a function (PR #5306), but it's not merged yet.

If you need a workaround now, set a global errorURL in your config or use middleware (e.g., in Next.js) to redirect /api/auth/error to your desired page. For full per-flow control, you'll need the code change you suggested or wait for the PR to be merged.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

<!-- gh-comment-id:3435919605 --> @dosubot[bot] commented on GitHub (Oct 23, 2025): <!-- Greeting --> Hi @noze12! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> You're correct—Better Auth v1.3.27 does not consistently respect `onAPIError.errorURL` in the OAuth callback flow. The code in [`state.ts`](https://github.com/better-auth/better-auth/blob/7641c0cf43d24812831ba2f933ad283c3f341489/packages/better-auth/src/oauth2/state.ts) hardcodes the error redirect to `${c.context.baseURL}/error` if `parsedData.errorURL` is missing, ignoring your config. Your suggested patch to use `c.context.options.onAPIError?.errorURL || ...` would fix this and unify error handling with other parts of the codebase [source](https://github.com/better-auth/better-auth/issues/2519). This limitation is well-known and discussed in several issues ([example](https://github.com/better-auth/better-auth/issues/4694)), with workarounds like setting a global errorURL or using middleware to intercept `/api/auth/error` and redirect to your custom page. There is an open PR to centralize and improve error URL handling, including support for custom error URLs via a function ([PR #5306](https://github.com/better-auth/better-auth/pull/5306)), but it's not merged yet. If you need a workaround now, set a global errorURL in your config or use middleware (e.g., in Next.js) to redirect `/api/auth/error` to your desired page. For full per-flow control, you'll need the code change you suggested or wait for the PR to be merged. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/d7ded968-3578-46d3-a4f6-fa0df32870bd?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/d7ded968-3578-46d3-a4f6-fa0df32870bd?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/d7ded968-3578-46d3-a4f6-fa0df32870bd?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/d7ded968-3578-46d3-a4f6-fa0df32870bd?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/d7ded968-3578-46d3-a4f6-fa0df32870bd?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/d7ded968-3578-46d3-a4f6-fa0df32870bd?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/d7ded968-3578-46d3-a4f6-fa0df32870bd?feedback_type=other)</sup>&nbsp;&nbsp;[![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&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/issues/5518)
Author
Owner

@DiegoGonzalezCruz commented on GitHub (Oct 23, 2025):

Thanks, when is this gonna be addressed?

<!-- gh-comment-id:3437332074 --> @DiegoGonzalezCruz commented on GitHub (Oct 23, 2025): Thanks, when is this gonna be addressed?
Author
Owner

@GautamBytes commented on GitHub (Oct 23, 2025):

will be working on it!

<!-- gh-comment-id:3437830483 --> @GautamBytes commented on GitHub (Oct 23, 2025): will be working on it!
Author
Owner

@AntoninMarchardDev commented on GitHub (Nov 20, 2025):

@GautamBytes on what release can we find this change ? it seems it's not resolved on 1.3.34

<!-- gh-comment-id:3556497651 --> @AntoninMarchardDev commented on GitHub (Nov 20, 2025): @GautamBytes on what release can we find this change ? it seems it's not resolved on 1.3.34
Author
Owner

@GautamBytes commented on GitHub (Nov 20, 2025):

@GautamBytes on what release can we find this change ? it seems it's not resolved on 1.3.34

1.4 coming this friday!

<!-- gh-comment-id:3557083808 --> @GautamBytes commented on GitHub (Nov 20, 2025): > [@GautamBytes](https://github.com/GautamBytes) on what release can we find this change ? it seems it's not resolved on 1.3.34 1.4 coming this friday!
Author
Owner

@Gustavonobregab commented on GitHub (Dec 11, 2025):

@GautamBytes on what release can we find this change ? it seems it's not resolved on 1.3.34

1.4 coming this friday!

Any update? Still not working

<!-- gh-comment-id:3643528230 --> @Gustavonobregab commented on GitHub (Dec 11, 2025): > > [@GautamBytes](https://github.com/GautamBytes) on what release can we find this change ? it seems it's not resolved on 1.3.34 > > 1.4 coming this friday! Any update? Still not working
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#18905