Incorrect schema generation in the beta release #1481

Closed
opened 2026-03-13 08:42:35 -05:00 by GiteaMirror · 3 comments
Owner

Originally created by @body20002 on GitHub (Jul 8, 2025).

well it doesn't really work since it generate 2 primary keys :/

export const account = pgTable("account", {
  id: serial("id").primaryKey(),
  accountId: text("account_id").notNull(),
  providerId: text("provider_id").notNull(),
  userId: serial("user_id")
    .primaryKey() // <-- this is wrong!
    .notNull()
    .references(() => user.id, { onDelete: "cascade" }),
  accessToken: text("access_token"),
  refreshToken: text("refresh_token"),
  idToken: text("id_token"),
  accessTokenExpiresAt: timestamp("access_token_expires_at"),
  refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
  scope: text("scope"),
  password: text("password"),
  createdAt: timestamp("created_at").notNull(),
  updatedAt: timestamp("updated_at").notNull(),
});

Originally posted by @body20002 in #3308

Originally created by @body20002 on GitHub (Jul 8, 2025). > well it doesn't really work since it generate 2 primary keys :/ > ```ts > export const account = pgTable("account", { > id: serial("id").primaryKey(), > accountId: text("account_id").notNull(), > providerId: text("provider_id").notNull(), > userId: serial("user_id") > .primaryKey() // <-- this is wrong! > .notNull() > .references(() => user.id, { onDelete: "cascade" }), > accessToken: text("access_token"), > refreshToken: text("refresh_token"), > idToken: text("id_token"), > accessTokenExpiresAt: timestamp("access_token_expires_at"), > refreshTokenExpiresAt: timestamp("refresh_token_expires_at"), > scope: text("scope"), > password: text("password"), > createdAt: timestamp("created_at").notNull(), > updatedAt: timestamp("updated_at").notNull(), > }); > ``` _Originally posted by @body20002 in [#3308](https://github.com/better-auth/better-auth/issues/3308#issuecomment-3049875914)_
GiteaMirror added the bug label 2026-03-13 08:42:35 -05:00
Author
Owner

@body20002 commented on GitHub (Jul 8, 2025):

please review #3308 first.

@body20002 commented on GitHub (Jul 8, 2025): please review #3308 first.
Author
Owner

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

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

I reviewed #3308 and the related code. The core schema generator for Better Auth is designed so that only the id field is the primary key for the account table—even when useNumberId is enabled. The userId field should only be a foreign key referencing user.id, not a primary key. The presence of two primary keys (id and userId) in your generated schema is not expected behavior and does not match the current implementation logic for schema generation in the codebase (source, source).

Recent pull requests have fixed related issues, ensuring that when useNumberId is enabled, serial is used for the id primary key in PostgreSQL, and userId remains a foreign key (source). If you are still seeing userId marked as a primary key, check for custom plugins, field overrides, or schema merging in your config that might be adding .primaryKey() to userId. The default generator and adapters do not do this.

If you want to isolate the issue, try generating the schema with a minimal config and no plugins or custom field definitions. If the problem persists, share your full config and any customizations—there may be an edge case or merge conflict causing the double primary key.

To reply, just mention @dosu.


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

@dosubot[bot] commented on GitHub (Jul 8, 2025): <!-- Greeting --> Hi @body20002! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> I reviewed #3308 and the related code. The core schema generator for Better Auth is designed so that only the id field is the primary key for the account table—even when useNumberId is enabled. The userId field should only be a foreign key referencing user.id, not a primary key. The presence of two primary keys (id and userId) in your generated schema is not expected behavior and does not match the current implementation logic for schema generation in the codebase ([source](https://github.com/better-auth/better-auth/blob/c5d43bad6c4d45a7c0a09a7ab561bb0a219c522d/packages/cli/src/generators/drizzle.ts), [source](https://github.com/better-auth/better-auth/blob/c5d43bad6c4d45a7c0a09a7ab561bb0a219c522d/packages/better-auth/src/db/get-migration.ts)). Recent pull requests have fixed related issues, ensuring that when useNumberId is enabled, serial is used for the id primary key in PostgreSQL, and userId remains a foreign key ([source](https://github.com/better-auth/better-auth/pull/3228)). If you are still seeing userId marked as a primary key, check for custom plugins, field overrides, or schema merging in your config that might be adding .primaryKey() to userId. The default generator and adapters do not do this. If you want to isolate the issue, try generating the schema with a minimal config and no plugins or custom field definitions. If the problem persists, share your full config and any customizations—there may be an edge case or merge conflict causing the double primary key. <!-- 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/6ca5e413-9b01-4e3a-a171-8f70a76b6eaf?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/6ca5e413-9b01-4e3a-a171-8f70a76b6eaf?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/6ca5e413-9b01-4e3a-a171-8f70a76b6eaf?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/6ca5e413-9b01-4e3a-a171-8f70a76b6eaf?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/6ca5e413-9b01-4e3a-a171-8f70a76b6eaf?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/6ca5e413-9b01-4e3a-a171-8f70a76b6eaf?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/6ca5e413-9b01-4e3a-a171-8f70a76b6eaf?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/3310)
Author
Owner

@body20002 commented on GitHub (Jul 8, 2025):

it seems the issue is here c5d43bad6c/packages/cli/src/generators/drizzle.ts (L48)

			if (field.references?.field === "id") {
				if (options.advanced?.database?.useNumberId) {
					if (databaseType === "pg") {
						return `serial('${name}').primaryKey()`;
					} else if (databaseType === "mysql") {
						return `int('${name}').autoIncrement().primaryKey()`;
					} else {
						// using sqlite
						return `integer({ mode: 'number' }).primaryKey({ autoIncrement: true })`;
					}
				}
				return `text('${name}')`;
			}

this should be

			if (field.references?.field === "id") {
				if (options.advanced?.database?.useNumberId) {
					if (databaseType === "pg") {
						return `integer('${name}')`;
					} else if (databaseType === "mysql") {
						return `int('${name}')`;
					} else {
						// using sqlite
						return `integer({ mode: 'number' })`;
					}
				}
				return `text('${name}')`;
			}
@body20002 commented on GitHub (Jul 8, 2025): it seems the issue is here https://github.com/better-auth/better-auth/blob/c5d43bad6c4d45a7c0a09a7ab561bb0a219c522d/packages/cli/src/generators/drizzle.ts#L48 ```ts if (field.references?.field === "id") { if (options.advanced?.database?.useNumberId) { if (databaseType === "pg") { return `serial('${name}').primaryKey()`; } else if (databaseType === "mysql") { return `int('${name}').autoIncrement().primaryKey()`; } else { // using sqlite return `integer({ mode: 'number' }).primaryKey({ autoIncrement: true })`; } } return `text('${name}')`; } ``` this should be ```ts if (field.references?.field === "id") { if (options.advanced?.database?.useNumberId) { if (databaseType === "pg") { return `integer('${name}')`; } else if (databaseType === "mysql") { return `int('${name}')`; } else { // using sqlite return `integer({ mode: 'number' })`; } } return `text('${name}')`; } ```
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#1481