[GH-ISSUE #6994] fix: unsafe return of value of type any #28017

Closed
opened 2026-04-17 19:21:30 -05:00 by GiteaMirror · 6 comments
Owner

Originally created by @rbalet on GitHub (Dec 25, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/6994

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. While using Drizzle ORM
  2. Be sure eslint @typescript-eslint/no-unsafe-return is activated
  3. Create a plugin
import { BetterAuthPlugin } from "better-auth";

export const foosPlugin = () =>
  ({
    id: "foosPlugin",
    schema: {
      foo: {
        fields: {
          authorId: {
            type: "string",
            required: false,
            references: { model: "user", field: "id" },
          },
          mediaId: {
            type: "string",
            required: false,
            references: { model: "fooMedia", field: "id", onDelete: "set null" },
          },
        },
      },
      fooMedia: {
        fields: {
          fooId: {
            type: "string",
            required: true,
            references: { model: "foo", field: "id", onDelete: "cascade" },
          },
        },
      },
    },
  }) satisfies BetterAuthPlugin;
  1. run npx @better-auth/cli generate
  2. You'll get the following code
export const foo = pgTable("foo", {
  id: text("id").primaryKey(),
  authorId: text("author_id").references(() => user.id, {
    onDelete: "cascade",
  }),
  mediaId: text("media_id").references(() => fooMedia.id, {
    onDelete: "set null",
  }),
});

export const fooMedia = pgTable("foo_media", {
  id: text("id").primaryKey(),
  fooId: text("foo_id")
    .notNull()
    .references(() => foo.id, { onDelete: "cascade" }),
});

export const userRelations = relations(user, ({ many }) => ({
  sessions: many(session),
  accounts: many(account),
  foos: many(foo),
}));

export const fooRelations = relations(foo, ({ one, many }) => ({
  user: one(user, {
    fields: [foo.authorId],
    references: [user.id],
  }),
  fooMedia: one(fooMedia, {
    fields: [foo.mediaId],
    references: [fooMedia.id],
  }),
  fooMedias: many(fooMedia),
}));

export const fooMediaRelations = relations(fooMedia, ({ one, many }) => ({
  foo: one(foo, {
    fields: [fooMedia.fooId],
    references: [foo.id],
  }),
  foos: many(foo),
}));
  1. Add it to the plugins() import

Current vs. Expected behavior

Current

You'll get Unsafe return of a value of type any` on the following

  • fooMedia.id
  • fooMedia.fooId
  • foo.id
  • foo.authorId
  • foo.mediaId

Expected

no error, or maybe better explained one.

What version of Better Auth are you using?

1.4.9

System info

{
  "system": {
    "platform": "darwin",
    "arch": "arm64",
    "version": "Darwin Kernel Version 25.2.0: Tue Nov 18 21:07:05 PST 2025; root:xnu-12377.61.12~1/RELEASE_ARM64_T6020",
    "release": "25.2.0",
    "cpuCount": 12,
    "cpuModel": "Apple M2 Pro",
    "totalMemory": "32.00 GB",
    "freeMemory": "0.94 GB"
  },
  "node": {
    "version": "v24.11.1",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "11.7.0"
  },
  "frameworks": null,
  "databases": [
    {
      "name": "pg",
      "version": "8.16.3"
    },
    {
      "name": "drizzle",
      "version": "0.45.1"
    }
  ],
  "betterAuth": {
    "version": "1.4.4",
    "config": {
      "plugins": [
        {
          "name": "foosPlugin",
          "config": {
            "id": "foosPlugin",
            "schema": {
              "foo": {
                "fields": {
                  "authorId": {
                    "type": "string",
                    "required": false,
                    "references": {
                      "model": "user",
                      "field": "id"
                    }
                  },
                  "mediaId": {
                    "type": "string",
                    "required": false,
                    "references": {
                      "model": "fooMedia",
                      "field": "id",
                      "onDelete": "set null"
                    }
                  }
                }
              },
              "fooMedia": {
                "fields": {
                  "fooId": {
                    "type": "string",
                    "required": true,
                    "references": {
                      "model": "foo",
                      "field": "id",
                      "onDelete": "cascade"
                    }
                  }
                }
              }
            }
          }
        }
      ]
    }
  }
}

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

Backend

Auth config (if applicable)

import { betterAuth } from "better-auth"
export const auth = betterAuth({
  database: drizzleAdapter(database, { provider: "pg"}),
  plugins: [
   foosPlugin()
  ]
});

Additional context

No response

Originally created by @rbalet on GitHub (Dec 25, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/6994 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. While using Drizzle ORM 2. Be sure eslint `@typescript-eslint/no-unsafe-return` is activated 3. Create a plugin ```typescript import { BetterAuthPlugin } from "better-auth"; export const foosPlugin = () => ({ id: "foosPlugin", schema: { foo: { fields: { authorId: { type: "string", required: false, references: { model: "user", field: "id" }, }, mediaId: { type: "string", required: false, references: { model: "fooMedia", field: "id", onDelete: "set null" }, }, }, }, fooMedia: { fields: { fooId: { type: "string", required: true, references: { model: "foo", field: "id", onDelete: "cascade" }, }, }, }, }, }) satisfies BetterAuthPlugin; ``` 2. run `npx @better-auth/cli generate` 3. You'll get the following code ```typescript export const foo = pgTable("foo", { id: text("id").primaryKey(), authorId: text("author_id").references(() => user.id, { onDelete: "cascade", }), mediaId: text("media_id").references(() => fooMedia.id, { onDelete: "set null", }), }); export const fooMedia = pgTable("foo_media", { id: text("id").primaryKey(), fooId: text("foo_id") .notNull() .references(() => foo.id, { onDelete: "cascade" }), }); export const userRelations = relations(user, ({ many }) => ({ sessions: many(session), accounts: many(account), foos: many(foo), })); export const fooRelations = relations(foo, ({ one, many }) => ({ user: one(user, { fields: [foo.authorId], references: [user.id], }), fooMedia: one(fooMedia, { fields: [foo.mediaId], references: [fooMedia.id], }), fooMedias: many(fooMedia), })); export const fooMediaRelations = relations(fooMedia, ({ one, many }) => ({ foo: one(foo, { fields: [fooMedia.fooId], references: [foo.id], }), foos: many(foo), })); ``` 4. Add it to the `plugins()` import ### Current vs. Expected behavior ### Current You'll get `Unsafe return of a value of type `any` on the following - fooMedia.id - fooMedia.fooId - foo.id - foo.authorId - foo.mediaId ### Expected no error, or maybe better explained one. ### What version of Better Auth are you using? 1.4.9 ### System info ```bash { "system": { "platform": "darwin", "arch": "arm64", "version": "Darwin Kernel Version 25.2.0: Tue Nov 18 21:07:05 PST 2025; root:xnu-12377.61.12~1/RELEASE_ARM64_T6020", "release": "25.2.0", "cpuCount": 12, "cpuModel": "Apple M2 Pro", "totalMemory": "32.00 GB", "freeMemory": "0.94 GB" }, "node": { "version": "v24.11.1", "env": "development" }, "packageManager": { "name": "npm", "version": "11.7.0" }, "frameworks": null, "databases": [ { "name": "pg", "version": "8.16.3" }, { "name": "drizzle", "version": "0.45.1" } ], "betterAuth": { "version": "1.4.4", "config": { "plugins": [ { "name": "foosPlugin", "config": { "id": "foosPlugin", "schema": { "foo": { "fields": { "authorId": { "type": "string", "required": false, "references": { "model": "user", "field": "id" } }, "mediaId": { "type": "string", "required": false, "references": { "model": "fooMedia", "field": "id", "onDelete": "set null" } } } }, "fooMedia": { "fields": { "fooId": { "type": "string", "required": true, "references": { "model": "foo", "field": "id", "onDelete": "cascade" } } } } } } } ] } } } ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth" export const auth = betterAuth({ database: drizzleAdapter(database, { provider: "pg"}), plugins: [ foosPlugin() ] }); ``` ### Additional context _No response_
GiteaMirror added the lockedbug labels 2026-04-17 19:21:30 -05:00
Author
Owner

@better-auth-agent[bot] commented on GitHub (Dec 25, 2025):

It looks like you're experiencing an "unsafe return of value of type any" issue when using the Better Auth framework with TypeScript and the Drizzle ORM, specifically when running the npx @better-auth/cli generate. This might be related to type-checking constraints introduced in a recent version.

To address this, here are a few steps you can take:

  1. Check Typescript Configuration: Ensure your TypeScript configuration (tsconfig.json) allows strict types and is set up correctly to recognize the Better Auth types.

  2. Inspect Plugin Definitions: Review the plugin (foosPlugin) you've defined to ensure all fields and references are properly typed and declared, noting any fields returning any.

  3. Update Better Auth and Dependencies: Sometimes, type-related issues can be due to version mismatches. Make sure you are on the latest compatible version of Better Auth (as mentioned, 1.4.9) and Drizzle ORM.

  4. Error Reporting: If the problem persists, consider reporting this type issue on the Better Auth GitHub repository. This could help identify if it's an underlying issue in the Better Auth codebase that needs addressing.

  5. Check Existing Issues: There has been recent feedback on type-checking breaking in versions, which hints at complicating issues when updating to certain versions [1].

Feel free to tag @better-auth-agent, Beka, or Max for specific guidance on this, and let me know if you have any further questions! Are you currently facing any other issues with Better Auth?

If you need more help, tag @better-auth-agent in a comment so I can respond.

DiagramDiscordGitHub

Diagram Join Star

<!-- gh-comment-id:3691166340 --> @better-auth-agent[bot] commented on GitHub (Dec 25, 2025): It looks like you're experiencing an "unsafe return of value of type `any`" issue when using the Better Auth framework with TypeScript and the Drizzle ORM, specifically when running the `npx @better-auth/cli generate`. This might be related to type-checking constraints introduced in a recent version. To address this, here are a few steps you can take: 1. **Check Typescript Configuration**: Ensure your TypeScript configuration (`tsconfig.json`) allows strict types and is set up correctly to recognize the Better Auth types. 2. **Inspect Plugin Definitions**: Review the plugin (`foosPlugin`) you've defined to ensure all fields and references are properly typed and declared, noting any fields returning `any`. 3. **Update Better Auth and Dependencies**: Sometimes, type-related issues can be due to version mismatches. Make sure you are on the latest compatible version of Better Auth (as mentioned, 1.4.9) and Drizzle ORM. 4. **Error Reporting**: If the problem persists, consider reporting this type issue on the Better Auth GitHub repository. This could help identify if it's an underlying issue in the Better Auth codebase that needs addressing. 5. **Check Existing Issues**: There has been recent feedback on type-checking breaking in versions, which hints at complicating issues when updating to certain versions [[1]](https://github.com/better-auth/better-auth/issues/6965). Feel free to tag @better-auth-agent, Beka, or Max for specific guidance on this, and let me know if you have any further questions! Are you currently facing any other issues with Better Auth? _If you need more help, tag @better-auth-agent in a comment so I can respond._ <!-- bot:webhook reply v1 --> [Diagram](https://repodiagrams.s3.eu-north-1.amazonaws.com/skyvern_ultra_detailed_interactive.html) • [Discord](https://discord.gg/fG2XXEuQX3) • [GitHub](https://github.com/Skyvern-AI/Skyvern) [![Diagram](https://img.shields.io/badge/Diagram-2b3137?style=flat-square)](https://repodiagrams.s3.eu-north-1.amazonaws.com/skyvern_ultra_detailed_interactive.html) [![Join](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&style=flat-square)](https://discord.gg/fG2XXEuQX3) [![Star](https://img.shields.io/badge/star-181717?logo=github&logoColor=white&style=flat-square)](https://github.com/Skyvern-AI/Skyvern)
Author
Owner

@dosubot[bot] commented on GitHub (Dec 25, 2025):

This is a known limitation of the current Better Auth CLI code generation for Drizzle ORM: the generated schema uses string templates without explicit type annotations, so TypeScript can't infer the correct types for fields like fooMedia.id or foo.authorId. As a result, these fields are typed as any, which triggers the @typescript-eslint/no-unsafe-return lint error. This isn't caused by your plugin or config—it's a general issue with the code generator's approach and affects all generated Drizzle schemas in Better Auth as of v1.4.9 reference.

To work around this, you can manually annotate your generated tables using Drizzle's InferModel type helper. For example:

import { InferModel } from "drizzle-orm";
export type Foo = InferModel<typeof foo>;
export type FooMedia = InferModel<typeof fooMedia>;

You can also explicitly type usages of these fields in your code to avoid the unsafe return error.

There is no official fix yet, but the maintainers are aware of type safety and code generation issues and are working on improvements. For now, manual type annotation is the best way to restore type safety in your project. Keep an eye on future releases for updates reference.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

<!-- gh-comment-id:3691171196 --> @dosubot[bot] commented on GitHub (Dec 25, 2025): <!-- Answer --> This is a known limitation of the current Better Auth CLI code generation for Drizzle ORM: the generated schema uses string templates without explicit type annotations, so TypeScript can't infer the correct types for fields like `fooMedia.id` or `foo.authorId`. As a result, these fields are typed as `any`, which triggers the `@typescript-eslint/no-unsafe-return` lint error. This isn't caused by your plugin or config—it's a general issue with the code generator's approach and affects all generated Drizzle schemas in Better Auth as of v1.4.9 [reference](https://github.com/better-auth/better-auth/blob/35fcd1aa89b6e9978d7b34ec971066d6a8f1e4e3/packages/cli/src/generators/drizzle.ts#L20-L672). To work around this, you can manually annotate your generated tables using Drizzle's `InferModel` type helper. For example: ```typescript import { InferModel } from "drizzle-orm"; export type Foo = InferModel<typeof foo>; export type FooMedia = InferModel<typeof fooMedia>; ``` You can also explicitly type usages of these fields in your code to avoid the unsafe return error. There is no official fix yet, but the maintainers are aware of type safety and code generation issues and are working on improvements. For now, manual type annotation is the best way to restore type safety in your project. Keep an eye on future releases for updates [reference](https://github.com/better-auth/better-auth/issues/4250). <!-- 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/4bb189fa-10af-4922-b7bf-0e17de3c84b2?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/4bb189fa-10af-4922-b7bf-0e17de3c84b2?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/4bb189fa-10af-4922-b7bf-0e17de3c84b2?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/4bb189fa-10af-4922-b7bf-0e17de3c84b2?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/4bb189fa-10af-4922-b7bf-0e17de3c84b2?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/4bb189fa-10af-4922-b7bf-0e17de3c84b2?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/4bb189fa-10af-4922-b7bf-0e17de3c84b2?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=This%20is%20a%20known%20limitation%20of%20the%20current%20Better%20Auth%20CLI%20code%20generation%20for%20Drizzle%20ORM%3A%20the%20generated%20schema%20uses%20string%20templates%20without%20explicit%20type%20annotations%2C%20so%20TypeScript%20can%27t%20infer%20the%20correct%20types%20for%20fields%20like%20%60fooMedia.id%60%20or%20%60foo.authorId%60.%20As%20a%20result%2C%20these%20fields%20are%20typed%20as%20%60any%60%2C%20which%20triggers%20the%20%60%40typescript-eslint/no-unsafe-return%60%20lint%20error.%20This%20isn%27t%20caused%20by%20your%20plugin%20or%20config%E2%80%94it%27s%20a%20general%20issue%20with%20the%20code%20generator%27s%20approach%20and%20affects%20all%20generated%20Drizzle%20schemas%20in%20Better%20Auth%20as%20of%20v1.4.9%C2%A0%5Breference%5D%28https%3A//github.com/better-auth/better-auth/blob/35fcd1aa89b6e9978d7b34ec971066d6a8f1e4e3/packages/cli/src/generators/drizzle.ts%23L20-L672%29.%0A%0ATo%20work%20around%20this%2C%20you%20can%20manually%20annotate%20your%20generated%20tables%20using%20Drizzle%27s%20%60InferModel%60%20type%20helper.%20For%20example%3A%0A%0A%60%60%60typescript%0Aimport%20%7B%20InferModel%20%7D%20from%20%22drizzle-orm%22%3B%0Aexport%20type%20Foo%20%3D%20InferModel%3Ctypeof%20foo%3E%3B%0Aexport%20type%20FooMedia%20%3D%20InferModel%3Ctypeof%20fooMedia%3E%3B%0A%60%60%60%0A%0AYou%20can%20also%20explicitly%20type%20usages%20of%20these%20fields%20in%20your%20code%20to%20avoid%20the%20unsafe%20return%20error.%0A%0AThere%20is%20no%20official%20fix%20yet%2C%20but%20the%20maintainers%20are%20aware%20of%20type%20safety%20and%20code%20generation%20issues%20and%20are%20working%20on%20improvements.%20For%20now%2C%20manual%20type%20annotation%20is%20the%20best%20way%20to%20restore%20type%20safety%20in%20your%20project.%20Keep%20an%20eye%20on%20future%20releases%20for%20updates%C2%A0%5Breference%5D%28https%3A//github.com/better-auth/better-auth/issues/4250%29.)&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/6994)
Author
Owner

@rbalet commented on GitHub (Dec 25, 2025):

Ok, after deeper look, I found that the following was creating a circular dependency, which where creating the problem.

export const foo = pgTable("foo", {
  id: text("id").primaryKey(),
  authorId: text("author_id").references(() => user.id, {
    onDelete: "cascade",
  }),
  mediaId: text("media_id").references(() => fooMedia.id, {
    onDelete: "set null",
  }),
});

export const fooMedia = pgTable("foo_media", {
  id: text("id").primaryKey(),
  fooId: text("foo_id")
    .notNull()
    .references(() => foo.id, { onDelete: "cascade" }),
});

Removing the fooId from the fooMedia fixed the issue.

@dosu Should I close the issue or is this a real bug like you've mentioned ?

<!-- gh-comment-id:3691211865 --> @rbalet commented on GitHub (Dec 25, 2025): Ok, after deeper look, I found that the following was creating a circular dependency, which where creating the problem. ```typescript export const foo = pgTable("foo", { id: text("id").primaryKey(), authorId: text("author_id").references(() => user.id, { onDelete: "cascade", }), mediaId: text("media_id").references(() => fooMedia.id, { onDelete: "set null", }), }); export const fooMedia = pgTable("foo_media", { id: text("id").primaryKey(), fooId: text("foo_id") .notNull() .references(() => foo.id, { onDelete: "cascade" }), }); ``` Removing the `fooId` from the fooMedia fixed the issue. @dosu Should I close the issue or is this a real bug like you've mentioned ?
Author
Owner

@dosubot[bot] commented on GitHub (Dec 25, 2025):

This isn't a user error—it's a limitation of the current Better Auth CLI code generator. The generator doesn't detect or handle circular foreign key references, so when you have tables that reference each other, it can cause TypeScript to infer types as any, leading to the "unsafe return of value of type any" error. Removing the circular reference avoids the problem, but the underlying limitation remains in the generator itself, not your config or usage citation.

You can close the issue if it's no longer blocking you, but it's reasonable to keep it open as a limitation/feature request so maintainers are aware that circular references in plugin schemas currently aren't supported and can break type safety. If you need to work around this, avoid circular references or manually annotate types where needed.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

<!-- gh-comment-id:3691215166 --> @dosubot[bot] commented on GitHub (Dec 25, 2025): <!-- Answer --> This isn't a user error—it's a limitation of the current Better Auth CLI code generator. The generator doesn't detect or handle circular foreign key references, so when you have tables that reference each other, it can cause TypeScript to infer types as any, leading to the "unsafe return of value of type any" error. Removing the circular reference avoids the problem, but the underlying limitation remains in the generator itself, not your config or usage [citation](https://github.com/better-auth/better-auth/blob/35fcd1aa89b6e9978d7b34ec971066d6a8f1e4e3/packages/cli/src/generators/drizzle.ts#L20-L529). You can close the issue if it's no longer blocking you, but it's reasonable to keep it open as a limitation/feature request so maintainers are aware that circular references in plugin schemas currently aren't supported and can break type safety. If you need to work around this, avoid circular references or manually annotate types where needed. <!-- 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/a2fea265-8cbf-48e8-ba90-e019261cfe42?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/a2fea265-8cbf-48e8-ba90-e019261cfe42?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/a2fea265-8cbf-48e8-ba90-e019261cfe42?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/a2fea265-8cbf-48e8-ba90-e019261cfe42?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/a2fea265-8cbf-48e8-ba90-e019261cfe42?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/a2fea265-8cbf-48e8-ba90-e019261cfe42?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/a2fea265-8cbf-48e8-ba90-e019261cfe42?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=This%20isn%27t%20a%20user%20error%E2%80%94it%27s%20a%20limitation%20of%20the%20current%20Better%20Auth%20CLI%20code%20generator.%20The%20generator%20doesn%27t%20detect%20or%20handle%20circular%20foreign%20key%20references%2C%20so%20when%20you%20have%20tables%20that%20reference%20each%20other%2C%20it%20can%20cause%20TypeScript%20to%20infer%20types%20as%20any%2C%20leading%20to%20the%20%22unsafe%20return%20of%20value%20of%20type%20any%22%20error.%20Removing%20the%20circular%20reference%20avoids%20the%20problem%2C%20but%20the%20underlying%20limitation%20remains%20in%20the%20generator%20itself%2C%20not%20your%20config%20or%20usage%C2%A0%5Bcitation%5D%28https%3A//github.com/better-auth/better-auth/blob/35fcd1aa89b6e9978d7b34ec971066d6a8f1e4e3/packages/cli/src/generators/drizzle.ts%23L20-L529%29.%0A%0AYou%20can%20close%20the%20issue%20if%20it%27s%20no%20longer%20blocking%20you%2C%20but%20it%27s%20reasonable%20to%20keep%20it%20open%20as%20a%20limitation/feature%20request%20so%20maintainers%20are%20aware%20that%20circular%20references%20in%20plugin%20schemas%20currently%20aren%27t%20supported%20and%20can%20break%20type%20safety.%20If%20you%20need%20to%20work%20around%20this%2C%20avoid%20circular%20references%20or%20manually%20annotate%20types%20where%20needed.)&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/6994)
Author
Owner

@bytaesu commented on GitHub (Dec 25, 2025):

I think this is more of an issue with custom db design, and handling all cases in the CLI would increase complexity. I understand that this situation can occur, so I’ll close the issue for now 🙂

<!-- gh-comment-id:3691681989 --> @bytaesu commented on GitHub (Dec 25, 2025): I think this is more of an issue with custom db design, and handling all cases in the CLI would increase complexity. I understand that this situation can occur, so I’ll close the issue for now 🙂
Author
Owner

@rbalet commented on GitHub (Dec 26, 2025):

@bytaesu I understand, but does it make sense to close the issue then ?
Being able to have a one to one relationship with an external table, that is himself not directly linked to the user table would be quite helpful (Although I give you right, this is quite a complex case)

For the one who may face the same problem.
If you're doing a one-to-one relationship with a table that isn't directly linked to the user table

User <-> Foo <-> FooMedia

Then you can

1. Custom Schema

Have your own schema done with Zod and declares it inside your drizzle.config.ts file
You'll have to remove it from the plugin list then & Idk how it will work if you're sharing the plugin

export default defineConfig({
  schema: "./src/**/**.schema.ts",
  // ...

2. Manually handle the Foo -> FooMedia relationship

Remove the FooMedia to Foo relation
Seems this will work if you share the plugin, although not optimal

User <-> Foo -> FooMedia

But if you're creating or deleting FooMedia, then update his relation manually. Or something similar

async updateRelation(fooId: string, mediaId: string) {
  const updated = await this._database
    .update(schema.foo)
    .set({
      mediaId: mediaId,
    })
    .where(eq(schema.foo.id, fooId))
    .returning();

  if (!updated[0]) throw new NotFoundException("Foo not found");
  return updated[0];
}

Note: Idk what is the best option, just wished to share my findings

<!-- gh-comment-id:3692462376 --> @rbalet commented on GitHub (Dec 26, 2025): @bytaesu I understand, but does it make sense to close the issue then ? Being able to have a one to one relationship with an external table, that is himself not directly linked to the user table would be quite helpful _(Although I give you right, this is quite a complex case)_ For the one who may face the same problem. If you're doing a one-to-one relationship with a table that isn't directly linked to the user table `User <-> Foo <-> FooMedia` Then you can ## 1. Custom Schema Have your own schema done with Zod and declares it inside your `drizzle.config.ts` file _You'll have to remove it from the plugin list then & Idk how it will work if you're sharing the plugin_ ```typescript export default defineConfig({ schema: "./src/**/**.schema.ts", // ... ``` ## 2. Manually handle the Foo -> FooMedia relationship Remove the FooMedia to Foo relation _Seems this will work if you share the plugin, although not optimal_ `User <-> Foo -> FooMedia` But if you're creating or deleting `FooMedia`, then update his relation manually. _Or something similar_ ```typescript async updateRelation(fooId: string, mediaId: string) { const updated = await this._database .update(schema.foo) .set({ mediaId: mediaId, }) .where(eq(schema.foo.id, fooId)) .returning(); if (!updated[0]) throw new NotFoundException("Foo not found"); return updated[0]; } ``` _Note: Idk what is the best option, just wished to share my findings_
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#28017