[GH-ISSUE #1163] Using Drizzle Adapter with better-auth not working; TypeError: undefined is not an object (evaluating 'e._.fullSchema'). #25948

Closed
opened 2026-04-17 16:16:38 -05:00 by GiteaMirror · 7 comments
Owner

Originally created by @drtobbyas on GitHub (Jan 9, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/1163

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Create a Hono app
  2. Install drizzle-kit and pg
  3. install and setup better-auth
  4. setup better-auth with drizzle-adapter
  5. generate drizzle schema with better-auth
  6. run pnpm drizzle-kit generate and pnpm drizzle-kit migrate to setup tables and database
  7. Attempt to sign-up a user with email.

Current vs. Expected behavior

The server crash and it throws an Error when trying to sign up a user

This is the log of the error

2025-01-09T15:38:56.434Z ERROR [Better Auth]: TypeError 1 | import{and as z,asc as J,desc as G,eq as F,inArray as q,like as I,or as Q}from"drizzle-orm";import{z as s}from"zod";import{APIError as ne}from"better-call";var se=s.object({id:s.string(),providerId:s.string(),accountId:s.string(),userId:s.string(),accessToken:s.string().nullish(),refreshToken:s.string().nullish(),idToken:s.string().nullish(),accessTokenExpiresAt:s.date().nullish(),refreshTokenExpiresAt:s.date().nullish(),scope:s.string().nullish(),password:s.string().nullish(),createdAt:s.date().default(()=>new Date),updatedAt:s.date().default(()=>new Date)}),ie=s.object({id:s.string(),email:s.string().transform(e=>e.toLowerCase()),emailVerified:s.boolean().default(!1),name:s.string(),image:s.string().nullish(),createdAt:s.date().default(()=>new Date),updatedAt:s.date().default(()=>new Date)}),ae=s.object({id:s.string(),userId:s.string(),expiresAt:s.date(),createdAt:s.date().default(()=>new Date),updatedAt:s.date().default(()=>new Date),token:s.string(),ipAddress:s.string().nullish(),userAgent:s.string().null | ... truncated

TypeError: undefined is not an object (evaluating 'e._.fullSchema')

The Expected Behaviour: It should create a user with no error

Here is a video demo of the issue

https://github.com/user-attachments/assets/7cebea40-907b-4617-bcb0-1886f191e275

What version of Better Auth are you using?

1.1.10

Provide environment information

"better-auth": "^1.1.10",
    "drizzle-kit": "^0.30.1",
    "drizzle-orm": "^0.38.3",
    "hono": "^4.6.16",
    "pg": "^8.13.1"

Which area(s) are affected? (Select all that apply)

Backend, Client, Package

Auth config (if applicable)

import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { Pool } from "pg";
// import * as Schema from "@database/schema/auth.schema";

const queryClient = new Pool({
  connectionString: process.env.POSTGRES_URL,
  max: 50,
  idleTimeoutMillis: 30 * 1000, // 30 seconds
  connectionTimeoutMillis: 2 * 60 * 1000, // 2 minutes
});

export const auth = betterAuth({
  //   database: queryClient,
  database: drizzleAdapter(queryClient, {
    provider: "pg",
    // schema,
  }),

  trustedOrigins: [
    "http://localhost:3000",
    "http://localhost:8080",
    "http://localhost:8080/api/auth",
  ],
  emailAndPassword: {
    enabled: true,
  },

  // TODO: add social
});

Additional context

nothing more

Originally created by @drtobbyas on GitHub (Jan 9, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/1163 ### Is this suited for github? - [X] Yes, this is suited for github ### To Reproduce 1. Create a Hono app 2. Install drizzle-kit and pg 3. install and setup better-auth 4. setup better-auth with drizzle-adapter 5. generate drizzle schema with better-auth 6. run `pnpm drizzle-kit generate and pnpm drizzle-kit migrate` to setup tables and database 7. Attempt to sign-up a user with email. ### Current vs. Expected behavior The server crash and it throws an Error when trying to sign up a user This is the log of the error 2025-01-09T15:38:56.434Z ERROR [Better Auth]: TypeError 1 | import{and as z,asc as J,desc as G,eq as F,inArray as q,like as I,or as Q}from"drizzle-orm";import{z as s}from"zod";import{APIError as ne}from"better-call";var se=s.object({id:s.string(),providerId:s.string(),accountId:s.string(),userId:s.string(),accessToken:s.string().nullish(),refreshToken:s.string().nullish(),idToken:s.string().nullish(),accessTokenExpiresAt:s.date().nullish(),refreshTokenExpiresAt:s.date().nullish(),scope:s.string().nullish(),password:s.string().nullish(),createdAt:s.date().default(()=>new Date),updatedAt:s.date().default(()=>new Date)}),ie=s.object({id:s.string(),email:s.string().transform(e=>e.toLowerCase()),emailVerified:s.boolean().default(!1),name:s.string(),image:s.string().nullish(),createdAt:s.date().default(()=>new Date),updatedAt:s.date().default(()=>new Date)}),ae=s.object({id:s.string(),userId:s.string(),expiresAt:s.date(),createdAt:s.date().default(()=>new Date),updatedAt:s.date().default(()=>new Date),token:s.string(),ipAddress:s.string().nullish(),userAgent:s.string().null | ... truncated TypeError: undefined is not an object (evaluating 'e._.fullSchema') The Expected Behaviour: It should create a user with no error Here is a video demo of the issue https://github.com/user-attachments/assets/7cebea40-907b-4617-bcb0-1886f191e275 ### What version of Better Auth are you using? 1.1.10 ### Provide environment information ```bash "better-auth": "^1.1.10", "drizzle-kit": "^0.30.1", "drizzle-orm": "^0.38.3", "hono": "^4.6.16", "pg": "^8.13.1" ``` ### Which area(s) are affected? (Select all that apply) Backend, Client, Package ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth"; import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { Pool } from "pg"; // import * as Schema from "@database/schema/auth.schema"; const queryClient = new Pool({ connectionString: process.env.POSTGRES_URL, max: 50, idleTimeoutMillis: 30 * 1000, // 30 seconds connectionTimeoutMillis: 2 * 60 * 1000, // 2 minutes }); export const auth = betterAuth({ // database: queryClient, database: drizzleAdapter(queryClient, { provider: "pg", // schema, }), trustedOrigins: [ "http://localhost:3000", "http://localhost:8080", "http://localhost:8080/api/auth", ], emailAndPassword: { enabled: true, }, // TODO: add social }); ``` ### Additional context nothing more
GiteaMirror added the lockedbug labels 2026-04-17 16:16:38 -05:00
Author
Owner

@Nicolab commented on GitHub (Jan 16, 2025):

Hello,

Your initialization is not ok, it should look something like this instead:

const db = drizzle<typeof tables>({
  schema: tables,
  client: pool,
});

export const auth = betterAuth({
  database: drizzleAdapter(db, {
    provider: "pg",
    schema: authTables,
  }),
})

Related: https://orm.drizzle.team/docs/get-started-postgresql

<!-- gh-comment-id:2596221561 --> @Nicolab commented on GitHub (Jan 16, 2025): Hello, Your initialization is not ok, it should look something like this instead: ```ts const db = drizzle<typeof tables>({ schema: tables, client: pool, }); export const auth = betterAuth({ database: drizzleAdapter(db, { provider: "pg", schema: authTables, }), }) ``` Related: https://orm.drizzle.team/docs/get-started-postgresql
Author
Owner

@bookercodes commented on GitHub (May 1, 2025):

Looking at the code, Better Auth relies on the schema to understand the model at runtime.

You need to pass schema to Drizzle:

import * as schema from "@/db/schema";

export const db = drizzle(process.env.DATABASE_URL, { schema )

Or pass it to Better Auth's Drizzle adapter:

import * as schema from "@/db/schema";

export const auth = betterAuth({
    database: drizzleAdapter(db, {
        provider: "pg",
        schema
    }),
    emailAndPassword: {
        enabled: true
    }
});

Either is fine 👍

I ran into the same problem and I was a little bit surprised because you don't need to pass schema to use Drizzle ordinarily!

<!-- gh-comment-id:2844746949 --> @bookercodes commented on GitHub (May 1, 2025): Looking at the [code](https://github.com/better-auth/better-auth/blob/main/packages/better-auth/src/adapters/drizzle-adapter/drizzle-adapter.ts#L59), Better Auth relies on the `schema` to understand the model at runtime. You need to pass `schema` to Drizzle: ```ts import * as schema from "@/db/schema"; export const db = drizzle(process.env.DATABASE_URL, { schema ) ``` Or pass it to Better Auth's Drizzle adapter: ```ts import * as schema from "@/db/schema"; export const auth = betterAuth({ database: drizzleAdapter(db, { provider: "pg", schema }), emailAndPassword: { enabled: true } }); ``` Either is fine 👍 I ran into the same problem and I was a little bit surprised because you don't need to pass `schema` to use Drizzle ordinarily!
Author
Owner

@drtobbyas commented on GitHub (May 2, 2025):

ok, thanks

<!-- gh-comment-id:2847523434 --> @drtobbyas commented on GitHub (May 2, 2025): ok, thanks
Author
Owner

@delebash commented on GitHub (Jul 31, 2025):

This is not working for me.
drizzle 0.44.4
better-auth 1.3.4

src/utils/auth.ts

import { betterAuth } from 'better-auth'
import { drizzleAdapter } from 'better-auth/adapters/drizzle'
// import { db } from '../config/server.config.ts';
import * as schema from '../schema/schema.ts';
import 'dotenv/config';
import {drizzle} from "drizzle-orm/libsql";
export const db = drizzle(process.env.DATABASE_URL);


export const auth = betterAuth({
    database: drizzleAdapter(db, {
        provider: "sqlite", // or "pg" or "mysql"
        schema: {
            ...schema,
        },
  usePlural: true,
    }),
    emailAndPassword: {
        enabled: true
    }
});

also tried suggested comment above.


export const auth = betterAuth({
    database: drizzleAdapter(db, {
        provider: "sqlite",
        schema
    }),
    emailAndPassword: {
        enabled: true
    }
});

schema.ts

import { sqliteTable as table } from "drizzle-orm/sqlite-core";
import * as t from "drizzle-orm/sqlite-core";


export const test = table("test", {
    id: t.int().primaryKey({ autoIncrement: true }),
    name: t.text(),

});

run npx @better-auth/cli generate --config src/utils/auth.ts also ./src just in casae

no error msg and no schema file generated, also tried with --out.

<!-- gh-comment-id:3138581691 --> @delebash commented on GitHub (Jul 31, 2025): This is not working for me. drizzle 0.44.4 better-auth 1.3.4 src/utils/auth.ts ``` import { betterAuth } from 'better-auth' import { drizzleAdapter } from 'better-auth/adapters/drizzle' // import { db } from '../config/server.config.ts'; import * as schema from '../schema/schema.ts'; import 'dotenv/config'; import {drizzle} from "drizzle-orm/libsql"; export const db = drizzle(process.env.DATABASE_URL); export const auth = betterAuth({ database: drizzleAdapter(db, { provider: "sqlite", // or "pg" or "mysql" schema: { ...schema, }, usePlural: true, }), emailAndPassword: { enabled: true } }); ``` also tried suggested comment above. ``` export const auth = betterAuth({ database: drizzleAdapter(db, { provider: "sqlite", schema }), emailAndPassword: { enabled: true } }); ``` schema.ts ``` import { sqliteTable as table } from "drizzle-orm/sqlite-core"; import * as t from "drizzle-orm/sqlite-core"; export const test = table("test", { id: t.int().primaryKey({ autoIncrement: true }), name: t.text(), }); ``` run npx @better-auth/cli generate --config src/utils/auth.ts also ./src just in casae no error msg and no schema file generated, also tried with --out.
Author
Owner

@delebash commented on GitHub (Jul 31, 2025):

I uninstalled better-auth and drizzle and reinstalled. Now it is working.

<!-- gh-comment-id:3138724808 --> @delebash commented on GitHub (Jul 31, 2025): I uninstalled better-auth and drizzle and reinstalled. Now it is working.
Author
Owner

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

@bookercodes Which of the either methods would you recommend?

<!-- gh-comment-id:3290780481 --> @Ashvith10 commented on GitHub (Sep 15, 2025): @bookercodes Which of the either methods would you recommend?
Author
Owner

@Nicolab commented on GitHub (Nov 24, 2025):

@Ashvith10 it's the same. Except I initialize with an already instantiated pool (as in the official documentation) and I force the tables types. bookercodes use database URL instead of a pool.

It depends on your preference (pool or database URL, both are ok).

<!-- gh-comment-id:3570588003 --> @Nicolab commented on GitHub (Nov 24, 2025): @Ashvith10 it's the same. Except I initialize with an already instantiated pool (as in the official documentation) and I force the tables types. bookercodes use database URL instead of a pool. It depends on your preference (pool or database URL, both are ok).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#25948