[GH-ISSUE #3552] Difficulties setting up on Cloudflare D1 #9642

Closed
opened 2026-04-13 05:14:09 -05:00 by GiteaMirror · 2 comments
Owner

Originally created by @gokourt on GitHub (Jul 22, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/3552

Trying to setup better-auth on Cloudflare D1 (with Next.js).

export const auth = betterAuth({
  database: async () => {
    const context = await getCloudflareContext({ async: true });

    return new Kysely({
      dialect: new D1Dialect({
        database: context.env.DB,
      }),
    });
  },
  emailAndPassword: {
    enabled: true,
    autoSignIn: false,
  },
  socialProviders: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID as string,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
    },
  },
  plugins: [nextCookies()],
});

It looks like the adapter isn't being setup properly, because when I do

authClient.signIn.email({
  email: "test@example.com",
  password: "password",
}, {});

I get

# SERVER_ERROR:  [TypeError: adapter.findOne is not a function]
POST /api/auth/sign-in/email 500

and when I do

authClient.signIn.social({
  provider: "google",
});

I get

# SERVER_ERROR:  [TypeError: adapter.create is not a function]
POST /api/auth/sign-in/social 500

Not sure if I'm doing something wrong or this is a bug with better-auth.

Originally created by @gokourt on GitHub (Jul 22, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/3552 Trying to setup better-auth on Cloudflare D1 (with Next.js). ```js export const auth = betterAuth({ database: async () => { const context = await getCloudflareContext({ async: true }); return new Kysely({ dialect: new D1Dialect({ database: context.env.DB, }), }); }, emailAndPassword: { enabled: true, autoSignIn: false, }, socialProviders: { google: { clientId: process.env.GOOGLE_CLIENT_ID as string, clientSecret: process.env.GOOGLE_CLIENT_SECRET as string, }, }, plugins: [nextCookies()], }); ``` It looks like the adapter isn't being setup properly, because when I do ```js authClient.signIn.email({ email: "test@example.com", password: "password", }, {}); ``` I get ``` # SERVER_ERROR: [TypeError: adapter.findOne is not a function] POST /api/auth/sign-in/email 500 ``` and when I do ```js authClient.signIn.social({ provider: "google", }); ``` I get ``` # SERVER_ERROR: [TypeError: adapter.create is not a function] POST /api/auth/sign-in/social 500 ``` Not sure if I'm doing something wrong or this is a bug with better-auth.
GiteaMirror added the locked label 2026-04-13 05:14:09 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Jul 22, 2025):

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

The errors happen because better-auth expects the database property to be an adapter object, not a raw Kysely instance. To fix this, you need to wrap your Kysely instance with the kysely-adapter and specify the database type explicitly. For Cloudflare D1 (which is SQLite under the hood), your setup should look like this:

import { createKyselyAdapter } from '@better-auth/kysely-adapter';

export const auth = betterAuth({
  database: async () => {
    const context = await getCloudflareContext({ async: true });
    const db = new Kysely({
      dialect: new D1Dialect({
        database: context.env.DB,
      }),
    });
    return {
      adapter: createKyselyAdapter(db),
      type: 'sqlite', // D1 is SQLite-compatible
    };
  },
  // ...rest of your config
});

This ensures better-auth gets an object with the required adapter methods like findOne and create, resolving the TypeError you saw. See more details and examples in the discussion here.

To reply, just mention @dosu.


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

<!-- gh-comment-id:3104868921 --> @dosubot[bot] commented on GitHub (Jul 22, 2025): <!-- Greeting --> Hi @gokourt! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> The errors happen because better-auth expects the database property to be an adapter object, not a raw Kysely instance. To fix this, you need to wrap your Kysely instance with the kysely-adapter and specify the database type explicitly. For Cloudflare D1 (which is SQLite under the hood), your setup should look like this: ```js import { createKyselyAdapter } from '@better-auth/kysely-adapter'; export const auth = betterAuth({ database: async () => { const context = await getCloudflareContext({ async: true }); const db = new Kysely({ dialect: new D1Dialect({ database: context.env.DB, }), }); return { adapter: createKyselyAdapter(db), type: 'sqlite', // D1 is SQLite-compatible }; }, // ...rest of your config }); ``` This ensures better-auth gets an object with the required adapter methods like findOne and create, resolving the TypeError you saw. See more details and examples in the discussion [here](https://github.com/better-auth/better-auth/issues/3194). <!-- 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/b25994a0-222c-4244-b14a-2e95db5796c9?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/b25994a0-222c-4244-b14a-2e95db5796c9?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/b25994a0-222c-4244-b14a-2e95db5796c9?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/b25994a0-222c-4244-b14a-2e95db5796c9?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/b25994a0-222c-4244-b14a-2e95db5796c9?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/b25994a0-222c-4244-b14a-2e95db5796c9?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/b25994a0-222c-4244-b14a-2e95db5796c9?feedback_type=other)</sup>&nbsp;&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/3552)
Author
Owner

@gokourt commented on GitHub (Jul 23, 2025):

This worked:

async function initDb() {
  const context = await getCloudflareContext({ async: true });

  return new Kysely({
    dialect: new D1Dialect({
      database: context.env.DB,
    }),
  });
}

const db = await initDb();

export const auth = betterAuth({
  database: {
    db,
    type: "sqlite",
  },
  emailAndPassword: {
    enabled: true,
    autoSignIn: false,
  },
  socialProviders: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID as string,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
    },
  },
  plugins: [nextCookies()],
});
<!-- gh-comment-id:3109001881 --> @gokourt commented on GitHub (Jul 23, 2025): This worked: ```js async function initDb() { const context = await getCloudflareContext({ async: true }); return new Kysely({ dialect: new D1Dialect({ database: context.env.DB, }), }); } const db = await initDb(); export const auth = betterAuth({ database: { db, type: "sqlite", }, emailAndPassword: { enabled: true, autoSignIn: false, }, socialProviders: { google: { clientId: process.env.GOOGLE_CLIENT_ID as string, clientSecret: process.env.GOOGLE_CLIENT_SECRET as string, }, }, plugins: [nextCookies()], }); ```
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#9642