[GH-ISSUE #593] "TypeError: Invalid header value." on Cloudflare Pages #8331

Closed
opened 2026-04-13 03:23:55 -05:00 by GiteaMirror · 13 comments
Owner

Originally created by @lassegit on GitHub (Nov 19, 2024).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/593

Describe the bug

Returns 500 error saying: TypeError: Invalid header value. when trying to authenticate using Google on Cloudflare pages. This is the error message I get:

"message": [
  "%cBetter Auth:error%c ",
  "\n      background: #c0392b;\n      border-radius: 0.5em;\n      color: white;\n      font-weight: bold;\n      padding: 2px 0.5em;\n    ",
  "",
  "TypeError",
  "TypeError: Invalid header value."
],

I tried to deploy the "same" code to Vercel and it worked (of course without the modifications to make it work on the edge, e.g. factory functions for anything that uses environmental variables).

To Reproduce
Steps to reproduce the behavior:

  1. Go to https://www.websitefeedback.ai/signin/
  2. Click on Sign in button
  3. See error

Expected behavior

Should just authenticate.

Desktop (please complete the following information):

  • OS: Mac OSX
  • Browser: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36

Additional context

Better-Auth server handler than is mapped to the authentication route:

export const authServerFactory = ({
  DATABASE_URL,
  DATABASE_AUTH_TOKEN,
  GOOGLE_CLIENT_ID,
  GOOGLE_CLIENT_SECRET,
  BETTER_AUTH_URL,
  BETTER_AUTH_SECRET,
}: {
  DATABASE_URL: string;
  BETTER_AUTH_URL: string;
  BETTER_AUTH_SECRET: string;
  DATABASE_AUTH_TOKEN: string;
  GOOGLE_CLIENT_ID: string;
  GOOGLE_CLIENT_SECRET: string;
}) => {
  const db = dbFactory({ DATABASE_URL, DATABASE_AUTH_TOKEN });

  return betterAuth({
    baseURL: BETTER_AUTH_URL,
    secret: BETTER_AUTH_SECRET,
    // trustedOrigins: ['https://www.websitefeedback.ai', 'https://websitefeedback.ai', 'http://localhost:4321'],
    logger: {
      disabled: false,
      verboseLogging: true,
    },
    user: { modelName: 'users' },
    session: {
      modelName: 'sessions',
      cookieCache: {
        enabled: true,
        maxAge: 30 * 24 * 60 * 60, // Cache duration in seconds
      },
    },
    verification: { modelName: 'verifications' },
    account: { modelName: 'accounts' },
    database: drizzleAdapter(db, { provider: 'sqlite' }),
    socialProviders: {
      google: {
        clientId: GOOGLE_CLIENT_ID,
        clientSecret: GOOGLE_CLIENT_SECRET,
      },
    },
  });
};
Originally created by @lassegit on GitHub (Nov 19, 2024). Original GitHub issue: https://github.com/better-auth/better-auth/issues/593 **Describe the bug** Returns 500 error saying: `TypeError: Invalid header value.` when trying to authenticate using Google on Cloudflare pages. This is the error message I get: ``` "message": [ "%cBetter Auth:error%c ", "\n background: #c0392b;\n border-radius: 0.5em;\n color: white;\n font-weight: bold;\n padding: 2px 0.5em;\n ", "", "TypeError", "TypeError: Invalid header value." ], ``` I tried to deploy the "same" code to Vercel and it worked (of course without the modifications to make it work on the edge, e.g. factory functions for anything that uses environmental variables). **To Reproduce** Steps to reproduce the behavior: 1. Go to https://www.websitefeedback.ai/signin/ 2. Click on Sign in button 3. See error **Expected behavior** Should just authenticate. **Desktop (please complete the following information):** - OS: Mac OSX - Browser: `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36` **Additional context** Better-Auth server handler than is mapped to the authentication route: ```ts export const authServerFactory = ({ DATABASE_URL, DATABASE_AUTH_TOKEN, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, BETTER_AUTH_URL, BETTER_AUTH_SECRET, }: { DATABASE_URL: string; BETTER_AUTH_URL: string; BETTER_AUTH_SECRET: string; DATABASE_AUTH_TOKEN: string; GOOGLE_CLIENT_ID: string; GOOGLE_CLIENT_SECRET: string; }) => { const db = dbFactory({ DATABASE_URL, DATABASE_AUTH_TOKEN }); return betterAuth({ baseURL: BETTER_AUTH_URL, secret: BETTER_AUTH_SECRET, // trustedOrigins: ['https://www.websitefeedback.ai', 'https://websitefeedback.ai', 'http://localhost:4321'], logger: { disabled: false, verboseLogging: true, }, user: { modelName: 'users' }, session: { modelName: 'sessions', cookieCache: { enabled: true, maxAge: 30 * 24 * 60 * 60, // Cache duration in seconds }, }, verification: { modelName: 'verifications' }, account: { modelName: 'accounts' }, database: drizzleAdapter(db, { provider: 'sqlite' }), socialProviders: { google: { clientId: GOOGLE_CLIENT_ID, clientSecret: GOOGLE_CLIENT_SECRET, }, }, }); }; ```
GiteaMirror added the locked label 2026-04-13 03:23:55 -05:00
Author
Owner

@lassegit commented on GitHub (Nov 19, 2024):

Not really sure where to look for answers, tried debugging with various configurations without any luck.

<!-- gh-comment-id:2485176659 --> @lassegit commented on GitHub (Nov 19, 2024): Not really sure where to look for answers, tried debugging with various configurations without any luck.
Author
Owner

@Bekacru commented on GitHub (Nov 19, 2024):

what are you using as a web framework?

<!-- gh-comment-id:2485299882 --> @Bekacru commented on GitHub (Nov 19, 2024): what are you using as a web framework?
Author
Owner

@lassegit commented on GitHub (Nov 19, 2024):

I am using Astro v. 4.16.12.

<!-- gh-comment-id:2485635427 --> @lassegit commented on GitHub (Nov 19, 2024): I am using Astro v. `4.16.12`.
Author
Owner

@lassegit commented on GitHub (Nov 19, 2024):

It works locally and on Vercel. The console shows this stack trace;

https://www.websitefeedback.ai/api/auth/sign-in/social?currentURL=https%3A%2F%2Fwww.websitefeedback.ai%2Fsignin%2F 500 (Internal Server Error)
auth-client.BP1gVkd2.js:1
...
("pipeTo"in p && typeof p.pipeTo == "function" || typeof ((n = t?.body) == null ? void 0 : n.pipe) == "function") && ("duplex"in p || (p.duplex = "half"));
    const {clearTimeout: $} = ve(y, O);
    let d = await f(p.url, p);
    $();
...
<!-- gh-comment-id:2486184683 --> @lassegit commented on GitHub (Nov 19, 2024): It works locally and on Vercel. The console shows this stack trace; ``` https://www.websitefeedback.ai/api/auth/sign-in/social?currentURL=https%3A%2F%2Fwww.websitefeedback.ai%2Fsignin%2F 500 (Internal Server Error) auth-client.BP1gVkd2.js:1 ... ("pipeTo"in p && typeof p.pipeTo == "function" || typeof ((n = t?.body) == null ? void 0 : n.pipe) == "function") && ("duplex"in p || (p.duplex = "half")); const {clearTimeout: $} = ve(y, O); let d = await f(p.url, p); $(); ... ```
Author
Owner

@lassegit commented on GitHub (Nov 19, 2024):

Locally the initial POST request to/api/auth/sign-in/social?currentURL=http%3A%2F%2Flocalhost%3A3000%2Fsignin return an empty 200 response. This is the endpoint I presume: https://github.com/better-auth/better-auth/blob/main/packages/better-auth/src/api/routes/sign-in.ts#L10

Headers set on Cloudflare look identical to those on the Vercel deployment.

<!-- gh-comment-id:2486498867 --> @lassegit commented on GitHub (Nov 19, 2024): Locally the initial POST request to`/api/auth/sign-in/social?currentURL=http%3A%2F%2Flocalhost%3A3000%2Fsignin` return an empty 200 response. This is the endpoint I presume: https://github.com/better-auth/better-auth/blob/main/packages/better-auth/src/api/routes/sign-in.ts#L10 Headers set on Cloudflare look identical to those on the Vercel deployment.
Author
Owner

@avanderbergh commented on GitHub (Nov 20, 2024):

@lassegit I've just tried Google Auth on Cloudflare Pages on "astro": "5.0.0-beta.8" using "better-auth": "0.9.0-canary.1"

Seems to work now. Can you try with that?

<!-- gh-comment-id:2488194739 --> @avanderbergh commented on GitHub (Nov 20, 2024): @lassegit I've just tried Google Auth on Cloudflare Pages on `"astro": "5.0.0-beta.8"` using ` "better-auth": "0.9.0-canary.1"` Seems to work now. Can you try with that?
Author
Owner

@lassegit commented on GitHub (Nov 20, 2024):

@avanderbergh Which database are you using?

<!-- gh-comment-id:2488270750 --> @lassegit commented on GitHub (Nov 20, 2024): @avanderbergh Which database are you using?
Author
Owner

@lassegit commented on GitHub (Nov 20, 2024):

I fix the "Invalid header value" (was due to misconfigured variable in Cloudflare). I get further in the authentication process but still get an error:

ReferenceError: Buffer is not defined

On the URL: api/auth/callback/google?state=REDACTED&code=4%REDACTED&scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+openid&authuser=0&prompt=none.

Most likely because Node's Buffer module is used without importing it with import { Buffer } from 'node:buffer'; (see Cloudflare docs).

I will investigate further.

@Bekacru Does this help?

<!-- gh-comment-id:2488279122 --> @lassegit commented on GitHub (Nov 20, 2024): I fix the "Invalid header value" (was due to misconfigured variable in Cloudflare). I get further in the authentication process but still get an error: ``` ReferenceError: Buffer is not defined ``` On the URL: `api/auth/callback/google?state=REDACTED&code=4%REDACTED&scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+openid&authuser=0&prompt=none`. Most likely because Node's Buffer module is used without importing it with `import { Buffer } from 'node:buffer'; ` ([see Cloudflare docs](https://developers.cloudflare.com/workers/runtime-apis/nodejs/buffer/)). I will investigate further. @Bekacru Does this help?
Author
Owner

@avanderbergh commented on GitHub (Nov 20, 2024):

@lassegit

@avanderbergh Which database are you using?

Cloudflare D1

Here's my config:

import type { Database } from "@/db/types";
import { sendEmail } from "@/email";
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { magicLink } from "better-auth/plugins";
import type { SocialProviders } from "./types";

export const createServerAuth = ({
    db,
    resendKey,
    socialProviders,
}: {
    db: Database;
    resendKey: string;
    socialProviders: SocialProviders;
}) =>
    betterAuth({
        logger: {
            level: "debug",
        },
        account: {
            accountLinking: {
                enabled: true,
            },
        },
        database: drizzleAdapter(db, { provider: "sqlite" }),
        emailAndPassword: {
            enabled: true,
            requireEmailVerification: true,
            sendResetPassword: async ({ user, url }) => {
                await sendEmail({
                    to: user.email,
                    subject: "Reset your password",
                    html: `Click <a href="${url}">here</a> to reset your password.`,
                    resendKey: resendKey,
                });
            },
        },
        emailVerification: {
            sendOnSignUp: true,
            sendVerificationEmail: async ({ user, url }) => {
                await sendEmail({
                    to: user.email,
                    subject: "Verify your email",
                    html: `Click <a href="${url}">here</a> to verify your email.`,
                    resendKey: resendKey,
                });
            },
        },
        socialProviders,
        plugins: [
            magicLink({
                sendMagicLink: async ({ email, url }) => {
                    await sendEmail({
                        to: email,
                        subject: "Sign in to your account",
                        html: `Click <a href="${url}">here</a> to sign in.`,
                        resendKey: resendKey,
                    });
                },
            }),
        ],
    });
<!-- gh-comment-id:2488279481 --> @avanderbergh commented on GitHub (Nov 20, 2024): @lassegit > @avanderbergh Which database are you using? Cloudflare D1 Here's my config: ``` import type { Database } from "@/db/types"; import { sendEmail } from "@/email"; import { betterAuth } from "better-auth"; import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { magicLink } from "better-auth/plugins"; import type { SocialProviders } from "./types"; export const createServerAuth = ({ db, resendKey, socialProviders, }: { db: Database; resendKey: string; socialProviders: SocialProviders; }) => betterAuth({ logger: { level: "debug", }, account: { accountLinking: { enabled: true, }, }, database: drizzleAdapter(db, { provider: "sqlite" }), emailAndPassword: { enabled: true, requireEmailVerification: true, sendResetPassword: async ({ user, url }) => { await sendEmail({ to: user.email, subject: "Reset your password", html: `Click <a href="${url}">here</a> to reset your password.`, resendKey: resendKey, }); }, }, emailVerification: { sendOnSignUp: true, sendVerificationEmail: async ({ user, url }) => { await sendEmail({ to: user.email, subject: "Verify your email", html: `Click <a href="${url}">here</a> to verify your email.`, resendKey: resendKey, }); }, }, socialProviders, plugins: [ magicLink({ sendMagicLink: async ({ email, url }) => { await sendEmail({ to: email, subject: "Sign in to your account", html: `Click <a href="${url}">here</a> to sign in.`, resendKey: resendKey, }); }, }), ], }); ```
Author
Owner

@lassegit commented on GitHub (Nov 20, 2024):

Pretty similar to mine. Do you have a Wrangler/Node configuration file for your Astro project (that perhaps sets node_compat mode)?

I have a fork that imports Buffer when its used: https://github.com/lassegit/better-auth (might do a PR).

@avanderbergh

<!-- gh-comment-id:2488375274 --> @lassegit commented on GitHub (Nov 20, 2024): Pretty similar to mine. Do you have a Wrangler/Node configuration file for your Astro project (that perhaps sets `node_compat` mode)? I have a fork that imports Buffer when its used: https://github.com/lassegit/better-auth (might do a PR). @avanderbergh
Author
Owner

@avanderbergh commented on GitHub (Nov 20, 2024):

Pretty similar to mine. Do you have a Wrangler/Node configuration file for your Astro project (that perhaps sets node_compat mode)?

I have a fork that imports Buffer when its used: https://github.com/lassegit/better-auth (might do a PR).

@avanderbergh

@lassegit
Ah yes, I have compatibility_flags = ["nodejs_compat"] set.

<!-- gh-comment-id:2488412971 --> @avanderbergh commented on GitHub (Nov 20, 2024): > Pretty similar to mine. Do you have a Wrangler/Node configuration file for your Astro project (that perhaps sets `node_compat` mode)? > > I have a fork that imports Buffer when its used: https://github.com/lassegit/better-auth (might do a PR). > > @avanderbergh @lassegit Ah yes, I have `compatibility_flags = ["nodejs_compat"]` set.
Author
Owner

@avanderbergh commented on GitHub (Nov 20, 2024):

@lassegit

here

You can opt into improved Node.js compatibility by using nodejs_compat_v2 instead of nodejs_compat. This provides the functionality of nodejs_compat, but additionally you can import Node.js modules without the node: prefix and use polyfilled Node.js modules and globals that are not available with nodejs_compat.
On September 23, 2024, nodejs_compat will use the improved Node.js compatibility currently enabled with nodejs_compat_v2. This will require updating your compatibility_date to 2024-09-23 or later.

So if your compatibility_date < 2024-09-23, then compatibility_flags = ["nodejs_compat_v2"] should fix the issue for now?

<!-- gh-comment-id:2488496322 --> @avanderbergh commented on GitHub (Nov 20, 2024): @lassegit [here](https://developers.cloudflare.com/workers/configuration/compatibility-flags/#nodejs-compatibility-flag) > You can opt into improved Node.js compatibility by using `nodejs_compat_v2` instead of `nodejs_compat`. This provides the functionality of `nodejs_compat`, but additionally you can import Node.js modules without the node: prefix and use polyfilled Node.js modules and globals that are not available with `nodejs_compat`. On September 23, 2024, `nodejs_compat` will use the improved Node.js compatibility currently enabled with `nodejs_compat_v2`. This will require updating your compatibility_date to `2024-09-23` or later. So if your `compatibility_date` < `2024-09-23`, then `compatibility_flags = ["nodejs_compat_v2"]` should fix the issue for now?
Author
Owner

@lassegit commented on GitHub (Nov 20, 2024):

@avanderbergh Thanks. I add a wrangler.toml file (could also been set via Cloudflare dashboard):

name = "my_app"
pages_build_output_dir = "./dist"

compatibility_date = "2024-11-18"
compatibility_flags = [ "nodejs_compat_v2" ]
<!-- gh-comment-id:2488627530 --> @lassegit commented on GitHub (Nov 20, 2024): @avanderbergh Thanks. I add a `wrangler.toml` file (could also been set via Cloudflare dashboard): ```toml name = "my_app" pages_build_output_dir = "./dist" compatibility_date = "2024-11-18" compatibility_flags = [ "nodejs_compat_v2" ] ```
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#8331