APIError does not exist in target module "better-auth" #1585

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

Originally created by @meeshan-dev on GitHub (Jul 27, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

i imported import { APIError } from 'better-auth' in auth.ts, Nextjs shows error that APIError does not exist in target module "better-auth" but when i import import { APIError } from 'better-auth/api'; everything is fine.

Current vs. Expected behavior

this import does not work import { APIError } from 'better-auth';
but this works import { APIError } from 'better-auth/api';

What version of Better Auth are you using?

^1.2.9

Provide environment information

- OS: Pop!_OS 22.04 LTS (64 bit)
- Browser: Version 138.0.7204.100 (Official Build) (64-bit)

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

Backend

Auth config (if applicable)

import { db } from '@/db';
import { publicEnvVars } from '@/public-env-vars';
import { serverEnvVars } from '@/server-env-vars';
import { betterAuth } from 'better-auth';
import { APIError } from 'better-auth/api';
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
import { admin } from 'better-auth/plugins/admin';
import { emailOTP } from 'better-auth/plugins/email-otp';
import { genericOAuth } from 'better-auth/plugins/generic-oauth';
import { passkey } from 'better-auth/plugins/passkey';
import {
  accountDeletionEmailTemplate,
  otpEmailTemplate,
} from './email-templates';
import { notifyUser } from './notify-user';
import { sendEmail } from './send-email';

export const auth = betterAuth({
  database: drizzleAdapter(db, {
    provider: 'pg',
  }),
  emailAndPassword: { enabled: false },
  user: {
    deleteUser: {
      enabled: true,
      sendDeleteAccountVerification: async ({ url, user }) => {
        await notifyUser(user, {
          category: 'account-deletion',
          ...accountDeletionEmailTemplate({
            url,
            userName: user.name,
          }),
        });
      },
      beforeDelete: async (user) => {
        if (!('role' in user))
          throw new APIError('BAD_REQUEST', {
            message: 'User role must be defined.',
          });

        if (user.role === 'admin')
          throw new APIError('BAD_REQUEST', {
            message: 'Admin account cannot be deleted.',
          });
      },
    },
    changeEmail: {
      enabled: true,
      sendChangeEmailVerification: async ({ newEmail, url }) => {
        await sendEmail({
          from: {
            name: publicEnvVars.SITE_NAME,
            email: publicEnvVars.NO_REPLY_EMAIL,
          },
          to: [{ email: newEmail }],
          ...otpEmailTemplate({ url }),
        });
      },
    },
  },
  trustedOrigins: [publicEnvVars.SITE_URL],
  plugins: [
    admin(),
    passkey({
      rpName: publicEnvVars.SITE_NAME,
      rpID: new URL(publicEnvVars.SITE_URL).hostname,
    }),
    genericOAuth({
      config: [
        {
          providerId: 'google',
          clientId: serverEnvVars.GOOGLE_CLIENT_ID,
          clientSecret: serverEnvVars.GOOGLE_CLIENT_SECRET,
          discoveryUrl:
            'https://accounts.google.com/.well-known/openid-configuration',
          scopes: ['openid', 'email', 'profile'],
        },
      ],
    }),
    emailOTP({
      sendVerificationOnSignUp: true,
      sendVerificationOTP: async (data) => {
        await sendEmail({
          from: {
            name: publicEnvVars.SITE_NAME,
            email: publicEnvVars.NO_REPLY_EMAIL,
          },
          to: [{ email: data.email }],
          subject: `Your verification code: ${data.otp}`,
          category: 'OTP Verification',
          html: ``,
          text: ``,
        });
      },
    }),
  ],
});

Additional context

No response

Originally created by @meeshan-dev on GitHub (Jul 27, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce i imported `import { APIError } from 'better-auth'` in `auth.ts`, Nextjs shows error that `APIError` does not exist in target module "better-auth" but when i import `import { APIError } from 'better-auth/api';` everything is fine. ### Current vs. Expected behavior this import does not work `import { APIError } from 'better-auth';` but this works `import { APIError } from 'better-auth/api';` ### What version of Better Auth are you using? ^1.2.9 ### Provide environment information ```bash - OS: Pop!_OS 22.04 LTS (64 bit) - Browser: Version 138.0.7204.100 (Official Build) (64-bit) ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript import { db } from '@/db'; import { publicEnvVars } from '@/public-env-vars'; import { serverEnvVars } from '@/server-env-vars'; import { betterAuth } from 'better-auth'; import { APIError } from 'better-auth/api'; import { drizzleAdapter } from 'better-auth/adapters/drizzle'; import { admin } from 'better-auth/plugins/admin'; import { emailOTP } from 'better-auth/plugins/email-otp'; import { genericOAuth } from 'better-auth/plugins/generic-oauth'; import { passkey } from 'better-auth/plugins/passkey'; import { accountDeletionEmailTemplate, otpEmailTemplate, } from './email-templates'; import { notifyUser } from './notify-user'; import { sendEmail } from './send-email'; export const auth = betterAuth({ database: drizzleAdapter(db, { provider: 'pg', }), emailAndPassword: { enabled: false }, user: { deleteUser: { enabled: true, sendDeleteAccountVerification: async ({ url, user }) => { await notifyUser(user, { category: 'account-deletion', ...accountDeletionEmailTemplate({ url, userName: user.name, }), }); }, beforeDelete: async (user) => { if (!('role' in user)) throw new APIError('BAD_REQUEST', { message: 'User role must be defined.', }); if (user.role === 'admin') throw new APIError('BAD_REQUEST', { message: 'Admin account cannot be deleted.', }); }, }, changeEmail: { enabled: true, sendChangeEmailVerification: async ({ newEmail, url }) => { await sendEmail({ from: { name: publicEnvVars.SITE_NAME, email: publicEnvVars.NO_REPLY_EMAIL, }, to: [{ email: newEmail }], ...otpEmailTemplate({ url }), }); }, }, }, trustedOrigins: [publicEnvVars.SITE_URL], plugins: [ admin(), passkey({ rpName: publicEnvVars.SITE_NAME, rpID: new URL(publicEnvVars.SITE_URL).hostname, }), genericOAuth({ config: [ { providerId: 'google', clientId: serverEnvVars.GOOGLE_CLIENT_ID, clientSecret: serverEnvVars.GOOGLE_CLIENT_SECRET, discoveryUrl: 'https://accounts.google.com/.well-known/openid-configuration', scopes: ['openid', 'email', 'profile'], }, ], }), emailOTP({ sendVerificationOnSignUp: true, sendVerificationOTP: async (data) => { await sendEmail({ from: { name: publicEnvVars.SITE_NAME, email: publicEnvVars.NO_REPLY_EMAIL, }, to: [{ email: data.email }], subject: `Your verification code: ${data.otp}`, category: 'OTP Verification', html: ``, text: ``, }); }, }), ], }); ``` ### Additional context _No response_
Author
Owner

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

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

Importing APIError from 'better-auth/api' is the correct and intended approach. The main 'better-auth' entry point does not export APIError—this is by design and has been confirmed by maintainers and in community discussions. You should continue to use import { APIError } from 'better-auth/api' for your use case. For more context, see the relevant discussion and maintainer confirmation here and here.

If you’d like to see APIError exported from the main entry point in the future, you could suggest it as a feature request for improved developer experience.

To reply, just mention @dosu.


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

@dosubot[bot] commented on GitHub (Jul 27, 2025): <!-- Greeting --> Hi @7up-charsi! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> Importing APIError from 'better-auth/api' is the correct and intended approach. The main 'better-auth' entry point does not export APIError—this is by design and has been confirmed by maintainers and in community discussions. You should continue to use import { APIError } from 'better-auth/api' for your use case. For more context, see the relevant discussion and maintainer confirmation [here](https://github.com/better-auth/better-auth/issues/2949) and [here](https://github.com/better-auth/better-auth/discussions/3344). If you’d like to see APIError exported from the main entry point in the future, you could suggest it as a feature request for improved developer experience. <!-- 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/83806806-f8a6-4094-bb47-b19b9522f604?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/83806806-f8a6-4094-bb47-b19b9522f604?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/83806806-f8a6-4094-bb47-b19b9522f604?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/83806806-f8a6-4094-bb47-b19b9522f604?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/83806806-f8a6-4094-bb47-b19b9522f604?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/83806806-f8a6-4094-bb47-b19b9522f604?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/83806806-f8a6-4094-bb47-b19b9522f604?feedback_type=other)</sup>&nbsp;&nbsp;[![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&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/3644)
Author
Owner

@charlesevangelista602 commented on GitHub (Jul 27, 2025):

Skip to content
Navigation Menu
better-auth

Code
Issues
348
APIError does not exist in target module "better-auth" #3644
Open
Open
APIError does not exist in target module "better-auth"
#3644
Jump to bottom
Description
@7up-charsi
7up-charsi
opened 40 minutes ago
Is this suited for github?

Yes, this is suited for github
To Reproduce
i imported import { APIError } from 'better-auth' in auth.ts, Nextjs shows error that APIError does not exist in target module "better-auth" but when i import import { APIError } from 'better-auth/api'; everything is fine.

Current vs. Expected behavior
this import does not work import { APIError } from 'better-auth';
but this works import { APIError } from 'better-auth/api';

What version of Better Auth are you using?
^1.2.9

Provide environment information

  • OS: Pop!_OS 22.04 LTS (64 bit)
  • Browser: Version 138.0.7204.100 (Official Build) (64-bit)
    Which area(s) are affected? (Select all that apply)
    Backend

Auth config (if applicable)
import { db } from '@/db';
import { publicEnvVars } from '@/public-env-vars';
import { serverEnvVars } from '@/server-env-vars';
import { betterAuth } from 'better-auth';
import { APIError } from 'better-auth/api';
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
import { admin } from 'better-auth/plugins/admin';
import { emailOTP } from 'better-auth/plugins/email-otp';
import { genericOAuth } from 'better-auth/plugins/generic-oauth';
import { passkey } from 'better-auth/plugins/passkey';
import {
accountDeletionEmailTemplate,
otpEmailTemplate,
} from './email-templates';
import { notifyUser } from './notify-user';
import { sendEmail } from './send-email';

export const auth = betterAuth({
database: drizzleAdapter(db, {
provider: 'pg',
}),
emailAndPassword: { enabled: false },
user: {
deleteUser: {
enabled: true,
sendDeleteAccountVerification: async ({ url, user }) => {
await notifyUser(user, {
category: 'account-deletion',
...accountDeletionEmailTemplate({
url,
userName: user.name,
}),
});
},
beforeDelete: async (user) => {
if (!('role' in user))
throw new APIError('BAD_REQUEST', {
message: 'User role must be defined.',
});

    if (user.role === 'admin')
      throw new APIError('BAD_REQUEST', {
        message: 'Admin account cannot be deleted.',
      });
  },
},
changeEmail: {
  enabled: true,
  sendChangeEmailVerification: async ({ newEmail, url }) => {
    await sendEmail({
      from: {
        name: publicEnvVars.SITE_NAME,
        email: publicEnvVars.NO_REPLY_EMAIL,
      },
      to: [{ email: newEmail }],
      ...otpEmailTemplate({ url }),
    });
  },
},

},
trustedOrigins: [publicEnvVars.SITE_URL],
plugins: [
admin(),
passkey({
rpName: publicEnvVars.SITE_NAME,
rpID: new URL(publicEnvVars.SITE_URL).hostname,
}),
genericOAuth({
config: [
{
providerId: 'google',
clientId: serverEnvVars.GOOGLE_CLIENT_ID,
clientSecret: serverEnvVars.GOOGLE_CLIENT_SECRET,
discoveryUrl:
'https://accounts.google.com/.well-known/openid-configuration',
scopes: ['openid', 'email', 'profile'],
},
],
}),
emailOTP({
sendVerificationOnSignUp: true,
sendVerificationOTP: async (data) => {
await sendEmail({
from: {
name: publicEnvVars.SITE_NAME,
email: publicEnvVars.NO_REPLY_EMAIL,
},
to: [{ email: data.email }],
subject: Your verification code: ${data.otp},
category: 'OTP Verification',
html: , text: ,
});
},
}),
],
});
Additional context
No response

Activity
dosubot commented 37 minutes ago
@dosubot
dosubot
bot
37 minutes ago
Hi @7up-charsi! I'm Dosu and I’m helping the better-auth team.

Importing APIError from 'better-auth/api' is the correct and intended approach. The main 'better-auth' entry point does not export APIError—this is by design and has been confirmed by maintainers and in community discussions. You should continue to use import { APIError } from 'better-auth/api' for your use case. For more context, see the relevant discussion and maintainer confirmation here and here.

If you’d like to see APIError exported from the main entry point in the future, you could suggest it as a feature request for improved developer experience.

To reply, just mention @dosu.

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

charlesevangelista602
Add a comment
new Comment
Markdown input: edit mode selected.
Write
Preview
Use Markdown to format your comment
Remember, contributions to this repository should follow its contributing guidelines and security policy.
Metadata
Assignees
No one assigned
Labels
No labels
Type
No type
Projects
No projects
Milestone
No milestone
Relationships
None yet
Development
No branches or pull requests
NotificationsCustomize
You're not receiving notifications from this thread.

Participants
@7up-charsi
Issue actions
Footer
© 2025 GitHub, Inc.
Footer navigation
Term
Tevacy
Security
Status
Docs
Contact
Manage cookies
Do not share my personal information
APIError does not exist in target module "better-auth" · Issue #3644 · better-auth/better-auth348 result

@charlesevangelista602 commented on GitHub (Jul 27, 2025): Skip to content Navigation Menu better-auth Code Issues 348 APIError does not exist in target module "better-auth" #3644 Open Open APIError does not exist in target module "better-auth" #3644 Jump to bottom Description @7up-charsi 7up-charsi opened 40 minutes ago Is this suited for github? Yes, this is suited for github To Reproduce i imported import { APIError } from 'better-auth' in auth.ts, Nextjs shows error that APIError does not exist in target module "better-auth" but when i import import { APIError } from 'better-auth/api'; everything is fine. Current vs. Expected behavior this import does not work import { APIError } from 'better-auth'; but this works import { APIError } from 'better-auth/api'; What version of Better Auth are you using? ^1.2.9 Provide environment information - OS: Pop!_OS 22.04 LTS (64 bit) - Browser: Version 138.0.7204.100 (Official Build) (64-bit) Which area(s) are affected? (Select all that apply) Backend Auth config (if applicable) import { db } from '@/db'; import { publicEnvVars } from '@/public-env-vars'; import { serverEnvVars } from '@/server-env-vars'; import { betterAuth } from 'better-auth'; import { APIError } from 'better-auth/api'; import { drizzleAdapter } from 'better-auth/adapters/drizzle'; import { admin } from 'better-auth/plugins/admin'; import { emailOTP } from 'better-auth/plugins/email-otp'; import { genericOAuth } from 'better-auth/plugins/generic-oauth'; import { passkey } from 'better-auth/plugins/passkey'; import { accountDeletionEmailTemplate, otpEmailTemplate, } from './email-templates'; import { notifyUser } from './notify-user'; import { sendEmail } from './send-email'; export const auth = betterAuth({ database: drizzleAdapter(db, { provider: 'pg', }), emailAndPassword: { enabled: false }, user: { deleteUser: { enabled: true, sendDeleteAccountVerification: async ({ url, user }) => { await notifyUser(user, { category: 'account-deletion', ...accountDeletionEmailTemplate({ url, userName: user.name, }), }); }, beforeDelete: async (user) => { if (!('role' in user)) throw new APIError('BAD_REQUEST', { message: 'User role must be defined.', }); if (user.role === 'admin') throw new APIError('BAD_REQUEST', { message: 'Admin account cannot be deleted.', }); }, }, changeEmail: { enabled: true, sendChangeEmailVerification: async ({ newEmail, url }) => { await sendEmail({ from: { name: publicEnvVars.SITE_NAME, email: publicEnvVars.NO_REPLY_EMAIL, }, to: [{ email: newEmail }], ...otpEmailTemplate({ url }), }); }, }, }, trustedOrigins: [publicEnvVars.SITE_URL], plugins: [ admin(), passkey({ rpName: publicEnvVars.SITE_NAME, rpID: new URL(publicEnvVars.SITE_URL).hostname, }), genericOAuth({ config: [ { providerId: 'google', clientId: serverEnvVars.GOOGLE_CLIENT_ID, clientSecret: serverEnvVars.GOOGLE_CLIENT_SECRET, discoveryUrl: 'https://accounts.google.com/.well-known/openid-configuration', scopes: ['openid', 'email', 'profile'], }, ], }), emailOTP({ sendVerificationOnSignUp: true, sendVerificationOTP: async (data) => { await sendEmail({ from: { name: publicEnvVars.SITE_NAME, email: publicEnvVars.NO_REPLY_EMAIL, }, to: [{ email: data.email }], subject: `Your verification code: ${data.otp}`, category: 'OTP Verification', html: ``, text: ``, }); }, }), ], }); Additional context No response Activity dosubot commented 37 minutes ago @dosubot dosubot bot 37 minutes ago Hi @7up-charsi! I'm Dosu and I’m helping the better-auth team. Importing APIError from 'better-auth/api' is the correct and intended approach. The main 'better-auth' entry point does not export APIError—this is by design and has been confirmed by maintainers and in community discussions. You should continue to use import { APIError } from 'better-auth/api' for your use case. For more context, see the relevant discussion and maintainer confirmation here and here. If you’d like to see APIError exported from the main entry point in the future, you could suggest it as a feature request for improved developer experience. To reply, just mention @dosu. How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other Chat with Dosu Join Discord Share on X charlesevangelista602 Add a comment new Comment Markdown input: edit mode selected. Write Preview Use Markdown to format your comment Remember, contributions to this repository should follow its contributing guidelines and security policy. Metadata Assignees No one assigned Labels No labels Type No type Projects No projects Milestone No milestone Relationships None yet Development No branches or pull requests NotificationsCustomize You're not receiving notifications from this thread. Participants @7up-charsi Issue actions Footer © 2025 GitHub, Inc. Footer navigation Term Tevacy Security Status Docs Contact Manage cookies Do not share my personal information APIError does not exist in target module "better-auth" · Issue #3644 · better-auth/better-auth348 result
Author
Owner

@Kinfe123 commented on GitHub (Jul 27, 2025):

you can use that import from better-auth/api

@Kinfe123 commented on GitHub (Jul 27, 2025): you can use that import from `better-auth/api`
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#1585