BetterAuth api endpoints not working in Nuxt 3 app when deployed to cloudflare pages #1885

Closed
opened 2026-03-13 09:10:36 -05:00 by GiteaMirror · 10 comments
Owner

Originally created by @MartinLednar on GitHub (Sep 8, 2025).

So I am making Nuxt 3 application which I am deploying to Cloudflare pages.

My techstack is:

  • Nuxt v3.17.3
  • Postgres.js v3.4.7
  • Zod v3.25.28
  • DrizzleORM v0.44.5
  • BetterAuth v1.3.8

First I had problems with deploy and pg package so I followed the steps here and added the following to my nuxt.config.ts:

 nitro: {
    externals: {
      external: ["pg-native"],
    },
  }

This didn't help so I switched from pg to postgres.js. So now when I deploy I don't get any errors but when I call any of the BetterAuth api endpoints I get 500, but no good error message to share here.

So I created a separate api ednpoint which queries the DB and returns the data and it worked.

So this seems to be something specific to BetterAuth. Locally everything is working fine.

Specific endpoints which are failing:

`/api/auth/sign-in/email`, `/api/auth/sign-in/get-session`

In cloudflare pages logs for both of these endpoints I get the following:

 {
      "message": [
        "[request error] [unhandled] [POST] https://page.com/api/auth/sign-in/email\n",
        {
          "message": "Class extends value [object Module] is not a constructor or null",
          "statusCode": 500
        }
      ],
      "level": "error",
      "timestamp": 1757344987396
    }

My db client server/db/index.ts :

import { drizzle } from "drizzle-orm/postgres-js";

export const useDb = () =>
  drizzle({
    connection: {
      url: process.env.DATABASE_URL,
    },
  });

/lib/auth-client.ts:

import { createAuthClient } from "better-auth/vue";

export const authClient = createAuthClient({});

/utils/auth.ts:

import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";

import { emailClient } from "./mailClient";
import { useDb } from "../server/db/index";
import * as schema from "../server/db/schemas/auth-schema";

export const auth = betterAuth({
  database: drizzleAdapter(useDb(), {
    provider: "pg",
    schema,
  }),
  emailAndPassword: {
    enabled: true,
    autoSignIn: false,
  },
  emailVerification: {
    sendOnSignUp: true,
    requireEmailVerification: true,
    sendVerificationEmail: async ({ user, url }) => {
      await emailClient.sendMail({
        to: user.email,
        subject: "Verify your email address",
        text: `Click the link to verify your email: ${url}`,
      });
    },
  },
});

When i deployed to Netlify BetterAuth endpoints are working there, but I would like to stay on cloudflare.

Thank you in advance for any suggestions.

Originally created by @MartinLednar on GitHub (Sep 8, 2025). So I am making Nuxt 3 application which I am deploying to Cloudflare pages. My techstack is: - Nuxt v3.17.3 - Postgres.js v3.4.7 - Zod v3.25.28 - DrizzleORM v0.44.5 - BetterAuth v1.3.8 First I had problems with deploy and `pg` package so I followed the steps [here](https://stackoverflow.com/questions/78498288/deploying-nuxt-app-with-postgres-to-cloudflare-fails) and added the following to my `nuxt.config.ts`: ```ts nitro: { externals: { external: ["pg-native"], }, } ``` This didn't help so I switched from `pg` to `postgres.js`. So now when I deploy I don't get any errors but when I call any of the BetterAuth api endpoints I get `500`, but no good error message to share here. So I created a separate api ednpoint which queries the DB and returns the data and it worked. So this seems to be something specific to BetterAuth. Locally everything is working fine. Specific endpoints which are failing: \`/api/auth/sign-in/email\`, \`/api/auth/sign-in/get-session\` In cloudflare pages logs for both of these endpoints I get the following: ``` { "message": [ "[request error] [unhandled] [POST] https://page.com/api/auth/sign-in/email\n", { "message": "Class extends value [object Module] is not a constructor or null", "statusCode": 500 } ], "level": "error", "timestamp": 1757344987396 } ``` My db client `server/db/index.ts` : ```ts import { drizzle } from "drizzle-orm/postgres-js"; export const useDb = () => drizzle({ connection: { url: process.env.DATABASE_URL, }, }); ``` `/lib/auth-client.ts`: ```ts import { createAuthClient } from "better-auth/vue"; export const authClient = createAuthClient({}); ``` `/utils/auth.ts`: ```ts import { betterAuth } from "better-auth"; import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { emailClient } from "./mailClient"; import { useDb } from "../server/db/index"; import * as schema from "../server/db/schemas/auth-schema"; export const auth = betterAuth({ database: drizzleAdapter(useDb(), { provider: "pg", schema, }), emailAndPassword: { enabled: true, autoSignIn: false, }, emailVerification: { sendOnSignUp: true, requireEmailVerification: true, sendVerificationEmail: async ({ user, url }) => { await emailClient.sendMail({ to: user.email, subject: "Verify your email address", text: `Click the link to verify your email: ${url}`, }); }, }, }); ``` When i deployed to Netlify BetterAuth endpoints are working there, but I would like to stay on cloudflare. Thank you in advance for any suggestions.
GiteaMirror added the nuxt label 2026-03-13 09:10:36 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Sep 8, 2025):

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

Your error (Class extends value [object Module] is not a constructor or null) is a known ESM/CJS interop issue that often happens when a module is imported incorrectly—usually when a default export is expected but the module loader provides a namespace object instead. This is especially common in serverless environments like Cloudflare Pages, which handle modules differently than local or Netlify builds.

The root cause is usually a dependency (often better-call) being bundled or resolved incorrectly. Here are the most effective workarounds:

  • In your package.json, add an override to force better-call to version 1.0.15 or 1.0.15-beta.1, which fixes bundler compatibility issues:

    "overrides": {
      "better-call": "1.0.15"
    }
    

    See details and confirmation

  • If you use Vite (Nuxt 3 uses Vite under the hood), exclude better-auth from dependency optimization in your config:

    vite: {
      optimizeDeps: {
        exclude: ["better-auth"],
      },
    },
    

    See user report

  • If possible, downgrade BetterAuth to 1.3.7—users have reported that this version does not trigger the error in similar setups see thread.

  • Double-check that all database and BetterAuth server code is only imported and used in server-side files (never in client code or shared code).

These steps should resolve the error on Cloudflare Pages. If you still see issues, check your lockfile to ensure the correct better-call version is installed, and make sure your build output isn't accidentally bundling server code for the client.

To reply, just mention @dosu.


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

@dosubot[bot] commented on GitHub (Sep 8, 2025): <!-- Greeting --> Hi @MartinLednar! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> Your error (`Class extends value [object Module] is not a constructor or null`) is a known ESM/CJS interop issue that often happens when a module is imported incorrectly—usually when a default export is expected but the module loader provides a namespace object instead. This is especially common in serverless environments like Cloudflare Pages, which handle modules differently than local or Netlify builds. The root cause is usually a dependency (often `better-call`) being bundled or resolved incorrectly. Here are the most effective workarounds: - In your `package.json`, add an override to force `better-call` to version `1.0.15` or `1.0.15-beta.1`, which fixes bundler compatibility issues: ```json "overrides": { "better-call": "1.0.15" } ``` [See details and confirmation](https://github.com/better-auth/better-auth/issues/4082) - If you use Vite (Nuxt 3 uses Vite under the hood), exclude `better-auth` from dependency optimization in your config: ```ts vite: { optimizeDeps: { exclude: ["better-auth"], }, }, ``` [See user report](https://github.com/better-auth/better-auth/issues/4082) - If possible, downgrade BetterAuth to `1.3.7`—users have reported that this version does not trigger the error in similar setups [see thread](https://github.com/better-auth/better-auth/issues/4428). - Double-check that all database and BetterAuth server code is only imported and used in server-side files (never in client code or shared code). These steps should resolve the error on Cloudflare Pages. If you still see issues, check your lockfile to ensure the correct `better-call` version is installed, and make sure your build output isn't accidentally bundling server code for the client. <!-- 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/5be1de58-9465-4b61-936f-a3343dc3430a?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/5be1de58-9465-4b61-936f-a3343dc3430a?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/5be1de58-9465-4b61-936f-a3343dc3430a?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/5be1de58-9465-4b61-936f-a3343dc3430a?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/5be1de58-9465-4b61-936f-a3343dc3430a?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/5be1de58-9465-4b61-936f-a3343dc3430a?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/5be1de58-9465-4b61-936f-a3343dc3430a?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/4526)
Author
Owner

@MartinLednar commented on GitHub (Sep 8, 2025):

@dosu I tried your suggestions but it still didn't help

@MartinLednar commented on GitHub (Sep 8, 2025): @dosu I tried your suggestions but it still didn't help
Author
Owner

@dosubot[bot] commented on GitHub (Sep 8, 2025):

Sorry those steps didn’t help—this is a tricky Cloudflare/ESM interop issue that’s affected a lot of users. Here are the most effective next steps based on recent findings and what’s worked for others:

  1. Make sure your Cloudflare config (wrangler.toml or wrangler.json) sets a recent compatibility_date and includes compatibility_flags = ["nodejs_compat_v2"]. This enables Node.js polyfills and fixes issues like Buffer is not defined and other ESM/CJS quirks (example config).

  2. Move your BetterAuth and database initialization inside the API route handler (per-request), not at the module/global scope. This is crucial for Cloudflare’s runtime and has resolved similar errors for others (details and example, Hono/Cloudflare example). For Nuxt, this means creating the BetterAuth instance inside the handler for each request.

  3. Double-check that all BetterAuth and Drizzle code is only imported in server-only files, never in shared or client code.

  4. If you’re using email/password auth, be aware that password hashing can exceed Cloudflare’s CPU limits. Consider using social login, magic links, or a custom (less CPU-intensive) hash function if you see timeouts (see discussion).

  5. If you haven’t already, try downgrading to BetterAuth 1.3.7 as a temporary workaround—some regressions in 1.3.8 have caused new issues in edge/serverless environments.

If you’re still stuck, could you share your wrangler.toml (or wrangler.json) and a snippet showing exactly how/where you initialize BetterAuth and Drizzle in your Nuxt app? That will help pinpoint any remaining edge cases.

To reply, just mention @dosu.


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

@dosubot[bot] commented on GitHub (Sep 8, 2025): <!-- Answer --> Sorry those steps didn’t help—this is a tricky Cloudflare/ESM interop issue that’s affected a lot of users. Here are the most effective next steps based on recent findings and what’s worked for others: 1. Make sure your Cloudflare config (wrangler.toml or wrangler.json) sets a recent `compatibility_date` and includes `compatibility_flags = ["nodejs_compat_v2"]`. This enables Node.js polyfills and fixes issues like `Buffer is not defined` and other ESM/CJS quirks ([example config](https://github.com/better-auth/better-auth/issues/593#issuecomment-2573920459)). 2. Move your BetterAuth and database initialization inside the API route handler (per-request), not at the module/global scope. This is crucial for Cloudflare’s runtime and has resolved similar errors for others ([details and example](https://github.com/better-auth/better-auth/issues/969#issuecomment-2833532886), [Hono/Cloudflare example](https://github.com/better-auth/better-auth/issues/1143#issuecomment-2573920459)). For Nuxt, this means creating the BetterAuth instance inside the handler for each request. 3. Double-check that all BetterAuth and Drizzle code is only imported in server-only files, never in shared or client code. 4. If you’re using email/password auth, be aware that password hashing can exceed Cloudflare’s CPU limits. Consider using social login, magic links, or a custom (less CPU-intensive) hash function if you see timeouts ([see discussion](https://github.com/better-auth/better-auth/issues/969#issuecomment-2833532886)). 5. If you haven’t already, try downgrading to BetterAuth 1.3.7 as a temporary workaround—some regressions in 1.3.8 have caused new issues in edge/serverless environments. If you’re still stuck, could you share your wrangler.toml (or wrangler.json) and a snippet showing exactly how/where you initialize BetterAuth and Drizzle in your Nuxt app? That will help pinpoint any remaining edge cases. <!-- 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/19c6c91f-0ac0-42da-8580-ea09fe315887?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/19c6c91f-0ac0-42da-8580-ea09fe315887?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/19c6c91f-0ac0-42da-8580-ea09fe315887?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/19c6c91f-0ac0-42da-8580-ea09fe315887?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/19c6c91f-0ac0-42da-8580-ea09fe315887?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/19c6c91f-0ac0-42da-8580-ea09fe315887?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/19c6c91f-0ac0-42da-8580-ea09fe315887?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/4526)
Author
Owner

@himself65 commented on GitHub (Sep 11, 2025):

What's the db are you using?

@himself65 commented on GitHub (Sep 11, 2025): What's the db are you using?
Author
Owner

@himself65 commented on GitHub (Sep 11, 2025):

Have you tried bump the drizzle-orm version?

@himself65 commented on GitHub (Sep 11, 2025): Have you tried bump the drizzle-orm version?
Author
Owner

@MartinLednar commented on GitHub (Sep 12, 2025):

Hi @himself65 I am using supabase ( PostgreSQL ) and I have the latest version of drizzle-orm.

@MartinLednar commented on GitHub (Sep 12, 2025): Hi @himself65 I am using supabase ( PostgreSQL ) and I have the latest version of drizzle-orm.
Author
Owner

@MartinLednar commented on GitHub (Sep 15, 2025):

Hi @himself65 do you have any suggestions as to why this could be happending? I am finishing the project and this is a big blocker for me.

Thank you in advance.

@MartinLednar commented on GitHub (Sep 15, 2025): Hi @himself65 do you have any suggestions as to why this could be happending? I am finishing the project and this is a big blocker for me. Thank you in advance.
Author
Owner

@MartinLednar commented on GitHub (Sep 17, 2025):

For now I have resolved the issue by moving to Vercel

@MartinLednar commented on GitHub (Sep 17, 2025): For now I have resolved the issue by moving to Vercel
Author
Owner

@himself65 commented on GitHub (Oct 2, 2025):

I'm assuming this is related to serverless function

@himself65 commented on GitHub (Oct 2, 2025): I'm assuming this is related to serverless function
Author
Owner

@dosubot[bot] commented on GitHub (Jan 1, 2026):

Hi, @MartinLednar. I'm Dosu, and I'm helping the better-auth team manage their backlog and am marking this issue as stale.

Issue Summary:

  • You reported 500 errors with BetterAuth API endpoints when deploying a Nuxt 3 app to Cloudflare Pages.
  • The error involved "Class extends value [object Module] is not a constructor or null," indicating ESM/CJS interop issues specific to BetterAuth.
  • Suggested workarounds included forcing a specific better-call version, excluding better-auth from Vite optimization, moving initialization inside API handlers, and setting Cloudflare compatibility flags.
  • Despite these, the issue persisted on Cloudflare Pages.
  • You resolved the problem by switching deployment to Vercel, pointing to Cloudflare's serverless environment and module handling quirks as the root cause.

Next Steps:

  • Please confirm if this issue is still relevant with the latest version of better-auth or if the resolution via Vercel deployment fully addresses your concerns.
  • If it remains relevant, feel free to comment to keep the discussion open; otherwise, I will automatically close this issue in 7 days.

Thank you for your understanding and contribution!

@dosubot[bot] commented on GitHub (Jan 1, 2026): Hi, @MartinLednar. I'm [Dosu](https://dosu.dev), and I'm helping the better-auth team manage their backlog and am marking this issue as stale. **Issue Summary:** - You reported 500 errors with BetterAuth API endpoints when deploying a Nuxt 3 app to Cloudflare Pages. - The error involved "Class extends value [object Module] is not a constructor or null," indicating ESM/CJS interop issues specific to BetterAuth. - Suggested workarounds included forcing a specific better-call version, excluding better-auth from Vite optimization, moving initialization inside API handlers, and setting Cloudflare compatibility flags. - Despite these, the issue persisted on Cloudflare Pages. - You resolved the problem by switching deployment to Vercel, pointing to Cloudflare's serverless environment and module handling quirks as the root cause. **Next Steps:** - Please confirm if this issue is still relevant with the latest version of better-auth or if the resolution via Vercel deployment fully addresses your concerns. - If it remains relevant, feel free to comment to keep the discussion open; otherwise, I will automatically close this issue in 7 days. Thank you for your understanding and contribution!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#1885