[GH-ISSUE #3493] Exported variable 'auth' has or is using name 'OrganizationOptions' #9622

Closed
opened 2026-04-13 05:11:25 -05:00 by GiteaMirror · 15 comments
Owner

Originally created by @chaocwu on GitHub (Jul 20, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/3493

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

error:
Exported variable 'auth' has or is using name 'OrganizationOptions' from external module "/chao/react-hono-example/node_modules/better-auth/dist/plugins/organization/index" but cannot be named.ts(4023)

Current vs. Expected behavior

config:

import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { organization } from "better-auth/plugins";

import { db } from "../lib/db";
import * as schema from "../schemas/auth";

export const auth = betterAuth({
  database: drizzleAdapter(db, {
    provider: "pg",
    schema,
  }),
  trustedOrigins: [process.env.CORS_ORIGIN || "", "http://localhost:3000"],
  socialProviders: {
    github: {
      clientId: process.env.GITHUB_CLIENT_ID as string,
      clientSecret: process.env.GITHUB_CLIENT_SECRET as string,
    },
  },
  secret: process.env.BETTER_AUTH_SECRET,
  baseURL: process.env.BETTER_AUTH_URL,
  plugins: [organization()],
  databaseHooks: {
    user: {
      create: {
        after: async (user) => {
          await createDefaultOrganization(user);
        },
      },
    },
    session: {
      create: {
        before: async (session) => {
          return await setActiveOrganization(session);
        },
      },
    },
  },
});

async function createDefaultOrganization(user: typeof auth.$Infer.Session.user) {
  await auth.api.createOrganization({
    body: {
      userId: user.id,
      name: `${user.name}'s Organization`,
      slug: user.name,
    },
  });
}

async function setActiveOrganization(session: { userId: string }) {
  const firstOrg = await db.query.member.findFirst({
    where: (member, { eq }) => eq(member.userId, session.userId),
  });
  return {
    data: {
      ...session,
      activeOrganizationId: firstOrg?.organizationId,
    },
  };
}

What version of Better Auth are you using?

1.3.1

Provide environment information

linux

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

Backend, Types

Auth config (if applicable)

config:

import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { organization } from "better-auth/plugins";

import { db } from "../lib/db";
import * as schema from "../schemas/auth";

export const auth = betterAuth({
  database: drizzleAdapter(db, {
    provider: "pg",
    schema,
  }),
  trustedOrigins: [process.env.CORS_ORIGIN || "", "http://localhost:3000"],
  socialProviders: {
    github: {
      clientId: process.env.GITHUB_CLIENT_ID as string,
      clientSecret: process.env.GITHUB_CLIENT_SECRET as string,
    },
  },
  secret: process.env.BETTER_AUTH_SECRET,
  baseURL: process.env.BETTER_AUTH_URL,
  plugins: [organization()],
  databaseHooks: {
    user: {
      create: {
        after: async (user) => {
          await createDefaultOrganization(user);
        },
      },
    },
    session: {
      create: {
        before: async (session) => {
          return await setActiveOrganization(session);
        },
      },
    },
  },
});

async function createDefaultOrganization(user: typeof auth.$Infer.Session.user) {
  await auth.api.createOrganization({
    body: {
      userId: user.id,
      name: `${user.name}'s Organization`,
      slug: user.name,
    },
  });
}

async function setActiveOrganization(session: { userId: string }) {
  const firstOrg = await db.query.member.findFirst({
    where: (member, { eq }) => eq(member.userId, session.userId),
  });
  return {
    data: {
      ...session,
      activeOrganizationId: firstOrg?.organizationId,
    },
  };
}

Additional context

No response

Originally created by @chaocwu on GitHub (Jul 20, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/3493 ### Is this suited for github? - [ ] Yes, this is suited for github ### To Reproduce error: Exported variable 'auth' has or is using name 'OrganizationOptions' from external module "/chao/react-hono-example/node_modules/better-auth/dist/plugins/organization/index" but cannot be named.ts(4023) ### Current vs. Expected behavior config: ```typescript import { betterAuth } from "better-auth"; import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { organization } from "better-auth/plugins"; import { db } from "../lib/db"; import * as schema from "../schemas/auth"; export const auth = betterAuth({ database: drizzleAdapter(db, { provider: "pg", schema, }), trustedOrigins: [process.env.CORS_ORIGIN || "", "http://localhost:3000"], socialProviders: { github: { clientId: process.env.GITHUB_CLIENT_ID as string, clientSecret: process.env.GITHUB_CLIENT_SECRET as string, }, }, secret: process.env.BETTER_AUTH_SECRET, baseURL: process.env.BETTER_AUTH_URL, plugins: [organization()], databaseHooks: { user: { create: { after: async (user) => { await createDefaultOrganization(user); }, }, }, session: { create: { before: async (session) => { return await setActiveOrganization(session); }, }, }, }, }); async function createDefaultOrganization(user: typeof auth.$Infer.Session.user) { await auth.api.createOrganization({ body: { userId: user.id, name: `${user.name}'s Organization`, slug: user.name, }, }); } async function setActiveOrganization(session: { userId: string }) { const firstOrg = await db.query.member.findFirst({ where: (member, { eq }) => eq(member.userId, session.userId), }); return { data: { ...session, activeOrganizationId: firstOrg?.organizationId, }, }; } ``` ### What version of Better Auth are you using? 1.3.1 ### Provide environment information ```bash linux ``` ### Which area(s) are affected? (Select all that apply) Backend, Types ### Auth config (if applicable) ```typescript config: import { betterAuth } from "better-auth"; import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { organization } from "better-auth/plugins"; import { db } from "../lib/db"; import * as schema from "../schemas/auth"; export const auth = betterAuth({ database: drizzleAdapter(db, { provider: "pg", schema, }), trustedOrigins: [process.env.CORS_ORIGIN || "", "http://localhost:3000"], socialProviders: { github: { clientId: process.env.GITHUB_CLIENT_ID as string, clientSecret: process.env.GITHUB_CLIENT_SECRET as string, }, }, secret: process.env.BETTER_AUTH_SECRET, baseURL: process.env.BETTER_AUTH_URL, plugins: [organization()], databaseHooks: { user: { create: { after: async (user) => { await createDefaultOrganization(user); }, }, }, session: { create: { before: async (session) => { return await setActiveOrganization(session); }, }, }, }, }); async function createDefaultOrganization(user: typeof auth.$Infer.Session.user) { await auth.api.createOrganization({ body: { userId: user.id, name: `${user.name}'s Organization`, slug: user.name, }, }); } async function setActiveOrganization(session: { userId: string }) { const firstOrg = await db.query.member.findFirst({ where: (member, { eq }) => eq(member.userId, session.userId), }); return { data: { ...session, activeOrganizationId: firstOrg?.organizationId, }, }; } ``` ### Additional context _No response_
GiteaMirror added the locked label 2026-04-13 05:11:25 -05:00
Author
Owner

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

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

This TypeScript error (TS4023) happens because the OrganizationOptions type used by the organization plugin wasn't exported in a way that TypeScript could recognize in Better Auth v1.3.1. This is a known issue and was fixed in a recent update—specifically, after PR #3342 was merged on 2025-07-11. Upgrading Better Auth to a version after that date will resolve the error, as the type export was restructured to be compatible with TypeScript's requirements see PR #3342.

If you can't upgrade right away, workarounds that have helped with similar issues include using explicit type annotations, the satisfies keyword, or adjusting your tsconfig. For example, you can try:

const authConfig = { /* ... */ } satisfies BetterAuthOptions;
export const auth = betterAuth(authConfig) as ReturnType<typeof betterAuth<typeof authConfig>>;

This was a valid issue for GitHub because it was a real type export bug in the package, not a user error see discussion. Upgrading is the recommended fix.

To reply, just mention @dosu.


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

<!-- gh-comment-id:3092924955 --> @dosubot[bot] commented on GitHub (Jul 20, 2025): <!-- Greeting --> Hi @chaocwu! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> This TypeScript error (TS4023) happens because the OrganizationOptions type used by the organization plugin wasn't exported in a way that TypeScript could recognize in Better Auth v1.3.1. This is a known issue and was fixed in a recent update—specifically, after PR #3342 was merged on 2025-07-11. Upgrading Better Auth to a version after that date will resolve the error, as the type export was restructured to be compatible with TypeScript's requirements [see PR #3342](https://github.com/better-auth/better-auth/pull/3342). If you can't upgrade right away, workarounds that have helped with similar issues include using explicit type annotations, the satisfies keyword, or adjusting your tsconfig. For example, you can try: ```ts const authConfig = { /* ... */ } satisfies BetterAuthOptions; export const auth = betterAuth(authConfig) as ReturnType<typeof betterAuth<typeof authConfig>>; ``` This was a valid issue for GitHub because it was a real type export bug in the package, not a user error [see discussion](https://github.com/better-auth/better-auth/issues/2789). Upgrading is the recommended fix. <!-- 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/e06241b3-3bd3-4a1b-aee1-fbb2bbdd0760?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/e06241b3-3bd3-4a1b-aee1-fbb2bbdd0760?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/e06241b3-3bd3-4a1b-aee1-fbb2bbdd0760?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/e06241b3-3bd3-4a1b-aee1-fbb2bbdd0760?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/e06241b3-3bd3-4a1b-aee1-fbb2bbdd0760?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/e06241b3-3bd3-4a1b-aee1-fbb2bbdd0760?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/e06241b3-3bd3-4a1b-aee1-fbb2bbdd0760?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/3493)
Author
Owner

@chaocwu commented on GitHub (Jul 20, 2025):

@dosu
After modifying according to the repair method you provided, the problem still exists, and it is currently the latest version 1.3.1

error info:
Exported variable 'authConfig' has or is using name 'OrganizationOptions' from external module "/chao/react-hono-example/node_modules/better-auth/dist/plugins/organization/index" but cannot be named.ts(4023)

import { type BetterAuthOptions, betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { organization } from "better-auth/plugins";

import { db } from "../lib/db";
import * as schema from "../schemas/auth";

const authConfig = {
  database: drizzleAdapter(db, {
    provider: "pg",
    schema,
  }),
  trustedOrigins: [process.env.CORS_ORIGIN || "", "http://localhost:3000"],
  socialProviders: {
    github: {
      clientId: process.env.GITHUB_CLIENT_ID as string,
      clientSecret: process.env.GITHUB_CLIENT_SECRET as string,
    },
  },
  secret: process.env.BETTER_AUTH_SECRET,
  baseURL: process.env.BETTER_AUTH_URL,
  plugins: [organization()],
  databaseHooks: {
    user: {
      create: {
        after: async (user) => {
          await createDefaultOrganization(user);
        },
      },
    },
    session: {
      create: {
        before: async (session) => {
          return await setActiveOrganization(session);
        },
      },
    },
  },
} satisfies BetterAuthOptions;

export const auth = betterAuth(authConfig) as ReturnType<typeof betterAuth<typeof authConfig>>;

async function createDefaultOrganization(user: typeof auth.$Infer.Session.user) {
  await auth.api.createOrganization({
    body: {
      userId: user.id,
      name: `${user.name}'s Organization`,
      slug: user.name,
    },
  });
}

async function setActiveOrganization(session: { userId: string }) {
  const firstOrg = await db.query.member.findFirst({
    where: (member, { eq }) => eq(member.userId, session.userId),
  });
  return {
    data: {
      ...session,
      activeOrganizationId: firstOrg?.organizationId,
    },
  };
}

<!-- gh-comment-id:3093197480 --> @chaocwu commented on GitHub (Jul 20, 2025): @dosu After modifying according to the repair method you provided, the problem still exists, and it is currently the latest version 1.3.1 error info: Exported variable 'authConfig' has or is using name 'OrganizationOptions' from external module "/chao/react-hono-example/node_modules/better-auth/dist/plugins/organization/index" but cannot be named.ts(4023) ```typescript import { type BetterAuthOptions, betterAuth } from "better-auth"; import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { organization } from "better-auth/plugins"; import { db } from "../lib/db"; import * as schema from "../schemas/auth"; const authConfig = { database: drizzleAdapter(db, { provider: "pg", schema, }), trustedOrigins: [process.env.CORS_ORIGIN || "", "http://localhost:3000"], socialProviders: { github: { clientId: process.env.GITHUB_CLIENT_ID as string, clientSecret: process.env.GITHUB_CLIENT_SECRET as string, }, }, secret: process.env.BETTER_AUTH_SECRET, baseURL: process.env.BETTER_AUTH_URL, plugins: [organization()], databaseHooks: { user: { create: { after: async (user) => { await createDefaultOrganization(user); }, }, }, session: { create: { before: async (session) => { return await setActiveOrganization(session); }, }, }, }, } satisfies BetterAuthOptions; export const auth = betterAuth(authConfig) as ReturnType<typeof betterAuth<typeof authConfig>>; async function createDefaultOrganization(user: typeof auth.$Infer.Session.user) { await auth.api.createOrganization({ body: { userId: user.id, name: `${user.name}'s Organization`, slug: user.name, }, }); } async function setActiveOrganization(session: { userId: string }) { const firstOrg = await db.query.member.findFirst({ where: (member, { eq }) => eq(member.userId, session.userId), }); return { data: { ...session, activeOrganizationId: firstOrg?.organizationId, }, }; } ```
Author
Owner

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

The TS4023 error persists in v1.3.1 because the fix for the OrganizationOptions type export was merged after this release, so it's not included in your current version (details). The only permanent solution is to upgrade to a version after 2025-07-11.

If you can't upgrade right now, you can use one of these workarounds:

  • Add a type assertion to the plugin:

    import { BetterAuthPlugin } from "better-auth";
    // ...
    plugins: [organization() as unknown as BetterAuthPlugin],
    

    This disables type inference for the plugin, but avoids the export error.

  • Set declaration: false in your tsconfig.json:

    {
      "compilerOptions": {
        "declaration": false
      }
    }
    

    This disables type declaration file generation, which avoids the error if you don't need .d.ts files.

Both are temporary workarounds until you can upgrade to a version with the fix (reference).

To reply, just mention @dosu.


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

<!-- gh-comment-id:3093199202 --> @dosubot[bot] commented on GitHub (Jul 20, 2025): <!-- Answer --> The TS4023 error persists in v1.3.1 because the fix for the OrganizationOptions type export was merged after this release, so it's not included in your current version ([details](https://github.com/better-auth/better-auth/pull/3342)). The only permanent solution is to upgrade to a version after 2025-07-11. If you can't upgrade right now, you can use one of these workarounds: - Add a type assertion to the plugin: ```ts import { BetterAuthPlugin } from "better-auth"; // ... plugins: [organization() as unknown as BetterAuthPlugin], ``` This disables type inference for the plugin, but avoids the export error. - Set `declaration: false` in your `tsconfig.json`: ```json { "compilerOptions": { "declaration": false } } ``` This disables type declaration file generation, which avoids the error if you don't need `.d.ts` files. Both are temporary workarounds until you can upgrade to a version with the fix ([reference](https://github.com/better-auth/better-auth/issues/2789)). <!-- 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/37f8f772-caee-4566-b062-9f5f06f20590?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/37f8f772-caee-4566-b062-9f5f06f20590?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/37f8f772-caee-4566-b062-9f5f06f20590?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/37f8f772-caee-4566-b062-9f5f06f20590?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/37f8f772-caee-4566-b062-9f5f06f20590?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/37f8f772-caee-4566-b062-9f5f06f20590?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/37f8f772-caee-4566-b062-9f5f06f20590?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/3493)
Author
Owner

@Al-Azzani commented on GitHub (Jul 20, 2025):

I have the same issue in my monorepo but for both admin and org plugnins. Better-auth@1.3.1 and I use pnpm as package manager.

<!-- gh-comment-id:3094701059 --> @Al-Azzani commented on GitHub (Jul 20, 2025): I have the same issue in my monorepo but for both admin and org plugnins. Better-auth@1.3.1 and I use pnpm as package manager.
Author
Owner

@tomjurni commented on GitHub (Jul 21, 2025):

@dosu
I Upgraded to "better-auth": "^1.3.2" and still having this error in our admin and client plugins.

<!-- gh-comment-id:3095687896 --> @tomjurni commented on GitHub (Jul 21, 2025): @dosu I Upgraded to "better-auth": "^1.3.2" and still having this error in our admin and client plugins.
Author
Owner

@Thomascogez commented on GitHub (Jul 21, 2025):

Similar issue with the admin plugin

<!-- gh-comment-id:3095930776 --> @Thomascogez commented on GitHub (Jul 21, 2025): Similar issue with the admin plugin
Author
Owner

@yaseenawazah commented on GitHub (Jul 21, 2025):

I was able to solve it like this:

const organizationPlugin = (): ReturnType<typeof organization> =>
  organization({
    ...
  )}


export const auth = betterAuth({
  ...
  plugins:[organizationPlugin(), ....]
  ...
})

EDIT:
As pointed in one of the comments. this solution just gets rid of the type error in the auth config, but we lose the type references for the plugin functions.

<!-- gh-comment-id:3098679349 --> @yaseenawazah commented on GitHub (Jul 21, 2025): I was able to solve it like this: ```ts const organizationPlugin = (): ReturnType<typeof organization> => organization({ ... )} export const auth = betterAuth({ ... plugins:[organizationPlugin(), ....] ... }) ``` EDIT: As pointed in one of the comments. this solution just gets rid of the type error in the auth config, but we lose the type references for the plugin functions.
Author
Owner

@0xJJW commented on GitHub (Jul 21, 2025):

This might be irrelevant, but I had a similar error today whilst updating my fork of the org plugin. The issue was due to multiple versions of BetterAuth dependencies. For me, it was Zod and Better Call. After updating the affected packages, the issue was resolved.

I am using Turbo repo + pnpm

Here are the BetterAuth deps for 1.3.2

"dependencies": {
    "@better-auth/utils": "0.2.5",
    "@better-fetch/fetch": "^1.1.18",
    "@noble/ciphers": "^0.6.0",
    "@noble/hashes": "^1.8.0",
    "@simplewebauthn/browser": "^13.0.0",
    "@simplewebauthn/server": "^13.0.0",
    "better-call": "^1.0.12",
    "defu": "^6.1.4",
    "jose": "^5.9.6",
    "kysely": "^0.28.1",
    "nanostores": "^0.11.3",
    "zod": "^4.0.5"
  },
<!-- gh-comment-id:3099458698 --> @0xJJW commented on GitHub (Jul 21, 2025): This might be irrelevant, but I had a similar error today whilst updating my fork of the org plugin. The issue was due to multiple versions of BetterAuth dependencies. For me, it was Zod and Better Call. After updating the affected packages, the issue was resolved. I am using Turbo repo + pnpm Here are the BetterAuth deps for 1.3.2 ``` "dependencies": { "@better-auth/utils": "0.2.5", "@better-fetch/fetch": "^1.1.18", "@noble/ciphers": "^0.6.0", "@noble/hashes": "^1.8.0", "@simplewebauthn/browser": "^13.0.0", "@simplewebauthn/server": "^13.0.0", "better-call": "^1.0.12", "defu": "^6.1.4", "jose": "^5.9.6", "kysely": "^0.28.1", "nanostores": "^0.11.3", "zod": "^4.0.5" }, ```
Author
Owner

@r1me75 commented on GitHub (Jul 22, 2025):

I was able to solve it like this:

const organizationPlugin = (): ReturnType =>
organization({
...
)}

export const auth = betterAuth({
...
plugins:[organizationPlugin(), ....]
...
})

This approach resolves the error in auth.ts, but it results in the loss of type references to the server-side API methods of organization.

Image
<!-- gh-comment-id:3101726313 --> @r1me75 commented on GitHub (Jul 22, 2025): > I was able to solve it like this: > > const organizationPlugin = (): ReturnType<typeof organization> => > organization({ > ... > )} > > > export const auth = betterAuth({ > ... > plugins:[organizationPlugin(), ....] > ... > }) This approach resolves the error in auth.ts, but it results in the loss of type references to the server-side API methods of organization. <img width="369" height="69" alt="Image" src="https://github.com/user-attachments/assets/4e5ef92d-b9f7-44bd-aa80-0b1db57c1dc8" />
Author
Owner

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

I got a similar error with the admin plugin. Upgrading to the latest v1.3.3 doesn't help. I solved it by removing "compilerOptions.composite" from tsconfig.json or setting it to false. My setup is Bun monorepo.

<!-- gh-comment-id:3108959823 --> @nawawishkid commented on GitHub (Jul 23, 2025): I got a similar error with the admin plugin. Upgrading to the latest v1.3.3 doesn't help. I solved it by removing `"compilerOptions.composite"` from tsconfig.json or setting it to `false`. My setup is Bun monorepo.
Author
Owner

@Al-Azzani commented on GitHub (Jul 25, 2025):

I got a similar error with the admin plugin. Upgrading to the latest v1.3.3 doesn't help. I solved it by removing "compilerOptions.composite" from tsconfig.json or setting it to false. My setup is Bun monorepo.

I did this in my pnpm monorepo, and it broke the types shared between the apps. It solved the auth.ts issue though, but I cannot stick to this solution

<!-- gh-comment-id:3117854397 --> @Al-Azzani commented on GitHub (Jul 25, 2025): > I got a similar error with the admin plugin. Upgrading to the latest v1.3.3 doesn't help. I solved it by removing `"compilerOptions.composite"` from tsconfig.json or setting it to `false`. My setup is Bun monorepo. I did this in my pnpm monorepo, and it broke the types shared between the apps. It solved the auth.ts issue though, but I cannot stick to this solution
Author
Owner

@viktorbonino commented on GitHub (Jul 26, 2025):

i solved this by creating a package "better-auth" (im using a monorepo) where i have my config (with declaration and declarationMap set to false)

import { BetterAuthOptions } from 'better-auth'
import { admin } from 'better-auth/plugins'
import { organization } from 'better-auth/plugins'

export const authConfig = {
  emailAndPassword: {
    enabled: true,
  },
  plugins: [admin(), organization()],

  trustedOrigins: ['http://localhost:3000'],
} satisfies BetterAuthOptions

Then i imported the package in my app (with composite: true):

import { betterAuth, BetterAuthOptions } from 'better-auth'
import { drizzleAdapter, DB } from 'better-auth/adapters/drizzle'

import { createDb } from '@/db/db'
import * as schema from '@/db/auth-schema'
import { authConfig } from '@repo/better-auth/server'

const createConfig = (db: DB) => {
  return {
    ...authConfig,
    database: drizzleAdapter(db, {
      provider: 'pg',
      schema: schema,
    }),
  } satisfies BetterAuthOptions
}

export const createAuth = () => {
  const db = createDb()
  return betterAuth(createConfig(db)) as ReturnType<typeof betterAuth<typeof authConfig>>
}

(i'm using honojs with cloudflare workers, so i need to create a db connection everytime, but you can avoid to do it if using something else)

<!-- gh-comment-id:3122194494 --> @viktorbonino commented on GitHub (Jul 26, 2025): i solved this by creating a package "better-auth" (im using a monorepo) where i have my config (with declaration and declarationMap set to false) ```ts import { BetterAuthOptions } from 'better-auth' import { admin } from 'better-auth/plugins' import { organization } from 'better-auth/plugins' export const authConfig = { emailAndPassword: { enabled: true, }, plugins: [admin(), organization()], trustedOrigins: ['http://localhost:3000'], } satisfies BetterAuthOptions ``` Then i imported the package in my app (with composite: true): ```ts import { betterAuth, BetterAuthOptions } from 'better-auth' import { drizzleAdapter, DB } from 'better-auth/adapters/drizzle' import { createDb } from '@/db/db' import * as schema from '@/db/auth-schema' import { authConfig } from '@repo/better-auth/server' const createConfig = (db: DB) => { return { ...authConfig, database: drizzleAdapter(db, { provider: 'pg', schema: schema, }), } satisfies BetterAuthOptions } export const createAuth = () => { const db = createDb() return betterAuth(createConfig(db)) as ReturnType<typeof betterAuth<typeof authConfig>> } ``` (i'm using honojs with cloudflare workers, so i need to create a db connection everytime, but you can avoid to do it if using something else)
Author
Owner

@wawansoer commented on GitHub (Jul 30, 2025):

Solved: TS4023 – Exported variable 'auth' has or is using name 'OrganizationOptions' but cannot be named

Hi all, I ran into the same TypeScript issue:

TS4023: Exported variable 'auth' has or is using name 'OrganizationOptions' from external module [...] but cannot be named.

This happens because TypeScript can't serialize certain types imported from external packages when using export const auth: ReturnType<typeof betterAuth>. The fix is to explicitly annotate the type using ReturnType without leaking the internal plugin types.

Here's how I resolved it:

📌 auth.ts (Server)

import { prisma } from "@workspace/db";
import { betterAuth } from "better-auth";
import { prismaAdapter } from "better-auth/adapters/prisma";
import { admin, emailOTP, magicLink, organization } from "better-auth/plugins";
import {
  sendConfirmationEmail,
  sendOTPEmail,
  sendResetPasswordEmail,
} from "./email";
import { env } from "./env";

// ✅ Proper export without triggering TS4023
export const auth: ReturnType<typeof betterAuth> = betterAuth({
  database: prismaAdapter(prisma, {
    provider: "postgresql",
  }),

  emailAndPassword: {
    enabled: true,
    config: {
      async sendVerificationEmail({ email, url, user }) {
        await sendConfirmationEmail({
          to: email,
          confirmationUrl: url,
          username: user?.name,
        });
      },
      async sendPasswordResetEmail({ email, url, user }) {
        await sendResetPasswordEmail({
          to: email,
          resetUrl: url,
          username: user?.name,
        });
      },
    },
  },

  socialProviders: {
    google: {
      prompt: "select_account+consent",
      clientId: env.AUTH_GOOGLE_ID || "",
      clientSecret: env.AUTH_GOOGLE_SECRET || "",
    },
  },

  plugins: [
    magicLink({
      sendMagicLink: async ({ email, url }) => {
        await sendConfirmationEmail({ to: email, confirmationUrl: url });
      },
    }),
    emailOTP({
      async sendVerificationOTP({ email, otp }) {
        await sendOTPEmail({ to: email, otp });
      },
    }),
    organization({
      allowUserToCreateOrganization: async ({ email }) => {
        const whitelist = env.ADMIN_EMAILS?.split(",") || [];
        return whitelist.includes(email);
      },
    }),
    admin(),
  ],
});

📌 authClient.ts (Client)

import { createAuthClient } from "better-auth/client";
import {
  adminClient,
  emailOTPClient,
  magicLinkClient,
  organizationClient,
} from "better-auth/client/plugins";

// ✅ Also uses ReturnType to avoid type leaking
export const authClient: ReturnType<typeof createAuthClient> = createAuthClient({
  plugins: [
    magicLinkClient(),
    emailOTPClient(),
    organizationClient(),
    adminClient(),
  ],
});

Let me know if anyone else needs help adapting this for different plugin setups! 🙌

<!-- gh-comment-id:3136893185 --> @wawansoer commented on GitHub (Jul 30, 2025): ✅ **Solved: `TS4023` – Exported variable 'auth' has or is using name 'OrganizationOptions' but cannot be named** Hi all, I ran into the same TypeScript issue: ``` TS4023: Exported variable 'auth' has or is using name 'OrganizationOptions' from external module [...] but cannot be named. ``` This happens because TypeScript can't serialize certain types imported from external packages when using `export const auth: ReturnType<typeof betterAuth>`. The fix is to explicitly annotate the type using `ReturnType` **without leaking the internal plugin types.** Here's how I resolved it: **📌 `auth.ts` (Server)** ```ts import { prisma } from "@workspace/db"; import { betterAuth } from "better-auth"; import { prismaAdapter } from "better-auth/adapters/prisma"; import { admin, emailOTP, magicLink, organization } from "better-auth/plugins"; import { sendConfirmationEmail, sendOTPEmail, sendResetPasswordEmail, } from "./email"; import { env } from "./env"; // ✅ Proper export without triggering TS4023 export const auth: ReturnType<typeof betterAuth> = betterAuth({ database: prismaAdapter(prisma, { provider: "postgresql", }), emailAndPassword: { enabled: true, config: { async sendVerificationEmail({ email, url, user }) { await sendConfirmationEmail({ to: email, confirmationUrl: url, username: user?.name, }); }, async sendPasswordResetEmail({ email, url, user }) { await sendResetPasswordEmail({ to: email, resetUrl: url, username: user?.name, }); }, }, }, socialProviders: { google: { prompt: "select_account+consent", clientId: env.AUTH_GOOGLE_ID || "", clientSecret: env.AUTH_GOOGLE_SECRET || "", }, }, plugins: [ magicLink({ sendMagicLink: async ({ email, url }) => { await sendConfirmationEmail({ to: email, confirmationUrl: url }); }, }), emailOTP({ async sendVerificationOTP({ email, otp }) { await sendOTPEmail({ to: email, otp }); }, }), organization({ allowUserToCreateOrganization: async ({ email }) => { const whitelist = env.ADMIN_EMAILS?.split(",") || []; return whitelist.includes(email); }, }), admin(), ], }); ``` **📌 `authClient.ts` (Client)** ```ts import { createAuthClient } from "better-auth/client"; import { adminClient, emailOTPClient, magicLinkClient, organizationClient, } from "better-auth/client/plugins"; // ✅ Also uses ReturnType to avoid type leaking export const authClient: ReturnType<typeof createAuthClient> = createAuthClient({ plugins: [ magicLinkClient(), emailOTPClient(), organizationClient(), adminClient(), ], }); ``` Let me know if anyone else needs help adapting this for different plugin setups! 🙌
Author
Owner

@Ariastarcos commented on GitHub (Aug 4, 2025):

Solved: TS4023 – Exported variable 'auth' has or is using name 'OrganizationOptions' but cannot be named
...

This is not a solution, plugin types are removed from the auth/client when not explicitly declaring plugin types in the ReturnType<typeof createAuthClient>.

I hope the library maintainers are working on releasing some utilities to type both the betterAuth and it's client in a more maintainable manner. The following is simply an example, but could prove very valuable for TS code-bases with isolated modules.

export const authClient: CreateAuthClient<{
  plugins: {
    admin: true,
    organization: true,
    // ...
  },
}> = createAuthClient({
  plugins: [
    magicLinkClient(),
    emailOTPClient(),
    organizationClient(),
    adminClient(),
  ],
});
<!-- gh-comment-id:3149755957 --> @Ariastarcos commented on GitHub (Aug 4, 2025): > ✅ **Solved: `TS4023` – Exported variable 'auth' has or is using name 'OrganizationOptions' but cannot be named** > ... This is not a solution, plugin types are removed from the auth/client when not explicitly declaring plugin types in the `ReturnType<typeof createAuthClient>`. I hope the library maintainers are working on releasing some utilities to `type` both the `betterAuth` and it's client in a more maintainable manner. The following is simply an example, but could prove very valuable for TS code-bases with isolated modules. ```ts export const authClient: CreateAuthClient<{ plugins: { admin: true, organization: true, // ... }, }> = createAuthClient({ plugins: [ magicLinkClient(), emailOTPClient(), organizationClient(), adminClient(), ], });
Author
Owner

@Kinfe123 commented on GitHub (Sep 19, 2025):

The OrganizationOptions should already be fixed but force assertion is not the right way either the declaration: false for solving this and beside that it is already been issued. will be fixed soon.

<!-- gh-comment-id:3312182783 --> @Kinfe123 commented on GitHub (Sep 19, 2025): The OrganizationOptions should already be fixed but force assertion is not the right way either the declaration: false for solving this and beside that it is already been issued. will be fixed soon.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#9622