[GH-ISSUE #8765] CLI is missing dependency on @opentelemetry/api #19816

Open
opened 2026-04-15 19:10:14 -05:00 by GiteaMirror · 9 comments
Owner

Originally created by @kvanbere on GitHub (Mar 25, 2026).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/8765

Originally assigned to: @jonathansamines on GitHub.

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

This command that previously worked in v1.5.0 should work:

yarn dlx auth@latest generate --config src/lib/server/auth/index.cli.ts --output src/lib/server/db/auth-schema.ts -y

In PR 8711 based off canary, it currently does not:

node:internal/modules/package_json_reader:268
  throw new ERR_MODULE_NOT_FOUND(packageName, fileURLToPath(base), null);
        ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@opentelemetry/api' imported from /private/var/folders/hy/d7x_09b11h31rvkqs02d6xg80000gn/T/xfs-a58b2fdf/dlx-14379/node_modules/@better-auth/core/dist/instrumentation/tracer.mjs
    at Object.getPackageJSONURL (node:internal/modules/package_json_reader:268:9)
    at packageResolve (node:internal/modules/esm/resolve:768:81)
    at moduleResolve (node:internal/modules/esm/resolve:858:18)
    at defaultResolve (node:internal/modules/esm/resolve:990:11)
    at #cachedDefaultResolve (node:internal/modules/esm/loader:768:20)
    at ModuleLoader.resolve (node:internal/modules/esm/loader:745:38)
    at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:318:38)
    at #link (node:internal/modules/esm/module_job:208:49) {
  code: 'ERR_MODULE_NOT_FOUND'
}

Node.js v24.8.0

This is because @opentelemetry/api is set as a peer dependency, but it's not actually optional, even if you pass BETTER_AUTH_TELEMETRY=0 in .env.

To prove this is the case, the following command that explicitly adds @opentelemetry/api to the sandbox works fine:

yarn dlx -p auth@latest -p @opentelemetry/api auth generate --config src/lib/server/auth/index.cli.ts --output src/lib/server/db/auth-schema.ts -y

Note there is currently no need to add the other adapters manually here.

Current vs. Expected behavior

N/A

What version of Better Auth are you using?

https://pkg.pr.new/@better-auth/core@8711

System info

N/A

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

Other

Auth config (if applicable)

import { betterAuth } from "better-auth"
export const auth = betterAuth({
  emailAndPassword: {  
    enabled: true
  },
});

Additional context

No response

Originally created by @kvanbere on GitHub (Mar 25, 2026). Original GitHub issue: https://github.com/better-auth/better-auth/issues/8765 Originally assigned to: @jonathansamines on GitHub. ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce This command that previously worked in `v1.5.0` should work: ```sh yarn dlx auth@latest generate --config src/lib/server/auth/index.cli.ts --output src/lib/server/db/auth-schema.ts -y ``` In PR 8711 based off canary, it currently does not: ```sh node:internal/modules/package_json_reader:268 throw new ERR_MODULE_NOT_FOUND(packageName, fileURLToPath(base), null); ^ Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@opentelemetry/api' imported from /private/var/folders/hy/d7x_09b11h31rvkqs02d6xg80000gn/T/xfs-a58b2fdf/dlx-14379/node_modules/@better-auth/core/dist/instrumentation/tracer.mjs at Object.getPackageJSONURL (node:internal/modules/package_json_reader:268:9) at packageResolve (node:internal/modules/esm/resolve:768:81) at moduleResolve (node:internal/modules/esm/resolve:858:18) at defaultResolve (node:internal/modules/esm/resolve:990:11) at #cachedDefaultResolve (node:internal/modules/esm/loader:768:20) at ModuleLoader.resolve (node:internal/modules/esm/loader:745:38) at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:318:38) at #link (node:internal/modules/esm/module_job:208:49) { code: 'ERR_MODULE_NOT_FOUND' } Node.js v24.8.0 ``` This is because `@opentelemetry/api` is set as a peer dependency, but it's not actually optional, even if you pass `BETTER_AUTH_TELEMETRY=0` in `.env`. To prove this is the case, the following command that explicitly adds `@opentelemetry/api` to the sandbox works fine: ```sh yarn dlx -p auth@latest -p @opentelemetry/api auth generate --config src/lib/server/auth/index.cli.ts --output src/lib/server/db/auth-schema.ts -y ``` Note there is currently no need to add the other adapters manually here. ### Current vs. Expected behavior N/A ### What version of Better Auth are you using? https://pkg.pr.new/@better-auth/core@8711 ### System info ```bash N/A ``` ### Which area(s) are affected? (Select all that apply) Other ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth" export const auth = betterAuth({ emailAndPassword: { enabled: true }, }); ``` ### Additional context _No response_
GiteaMirror added the regressiondevtools labels 2026-04-15 19:10:14 -05:00
Author
Owner

@kvanbere commented on GitHub (Mar 25, 2026):

@dosu can you confirm?

<!-- gh-comment-id:4123012878 --> @kvanbere commented on GitHub (Mar 25, 2026): @dosu can you confirm?
Author
Owner

@dosubot[bot] commented on GitHub (Mar 25, 2026):

Yes, I can confirm this bug. The issue is valid.

Root cause: In packages/core/src/instrumentation/tracer.ts, @opentelemetry/api is imported with a static import at the top of the file:

import { SpanStatusCode, trace } from "@opentelemetry/api";

This executes unconditionally when the module loads—there's no dynamic import() or conditional logic checking BETTER_AUTH_TELEMETRY before the import.

The package is listed as a peerDependency in @better-auth/core, but when running via yarn dlx, peer dependencies aren't automatically installed, causing the ERR_MODULE_NOT_FOUND error.

Potential fixes:

  1. Use a dynamic import() with lazy loading when telemetry is actually needed
  2. Move @opentelemetry/api to regular dependencies
  3. Wrap the import in a try-catch with a no-op fallback

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:4123035484 --> @dosubot[bot] commented on GitHub (Mar 25, 2026): <!-- Answer --> Yes, I can confirm this bug. The issue is valid. **Root cause:** In [`packages/core/src/instrumentation/tracer.ts`](https://github.com/better-auth/better-auth/blob/03278b5ad62c4cea61a8373bb7fe522519b31a42/packages/core/src/instrumentation/tracer.ts#L1), `@opentelemetry/api` is imported with a **static import** at the top of the file: ```typescript import { SpanStatusCode, trace } from "@opentelemetry/api"; ``` This executes unconditionally when the module loads—there's no dynamic `import()` or conditional logic checking `BETTER_AUTH_TELEMETRY` before the import. The package is listed as a [peerDependency in @better-auth/core](https://github.com/better-auth/better-auth/blob/03278b5ad62c4cea61a8373bb7fe522519b31a42/packages/core/package.json#L170), but when running via `yarn dlx`, peer dependencies aren't automatically installed, causing the `ERR_MODULE_NOT_FOUND` error. **Potential fixes:** 1. Use a dynamic `import()` with lazy loading when telemetry is actually needed 2. Move `@opentelemetry/api` to regular dependencies 3. Wrap the import in a try-catch with a no-op fallback <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot?utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=brand-link).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/fa1d0924-3f05-489f-8fc9-15ea3b5e922c?feedback_type=great_response&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/fa1d0924-3f05-489f-8fc9-15ea3b5e922c?feedback_type=irrelevant_answer&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/fa1d0924-3f05-489f-8fc9-15ea3b5e922c?feedback_type=incorrect_sources&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/fa1d0924-3f05-489f-8fc9-15ea3b5e922c?feedback_type=too_verbose&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/fa1d0924-3f05-489f-8fc9-15ea3b5e922c?feedback_type=hallucination&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/fa1d0924-3f05-489f-8fc9-15ea3b5e922c?feedback_type=bug_report&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-bug_report) | [Other](https://app.dosu.dev/response-feedback/fa1d0924-3f05-489f-8fc9-15ea3b5e922c?feedback_type=other&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-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&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=chat-badge)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=Yes%2C%20I%20can%20confirm%20this%20bug.%20The%20issue%20is%20valid.%0A%0A%2A%2ARoot%20cause%3A%2A%2A%20In%20%5B%60packages/core/src/instrumentation/tracer.ts%60%5D%28https%3A//github.com/better-auth/better-auth/blob/03278b5ad62c4cea61a8373bb7fe522519b31a42/packages/core/src/instrumentation/tracer.ts%23L1%29%2C%20%60%40opentelemetry/api%60%20is%20imported%20with%20a%20%2A%2Astatic%20import%2A%2A%20at%20the%20top%20of%20the%20file%3A%0A%0A%60%60%60typescript%0Aimport%20%7B%20SpanStatusCode%2C%20trace%20%7D%20from%20%22%40opentelemetry/api%22%3B%0A%60%60%60%0A%0AThis%20executes%20unconditionally%20when%20the%20module%20loads%E2%80%94there%27s%20no%20dynamic%20%60import%28%29%60%20or%20conditional%20logic%20checking%20%60BETTER_AUTH_TELEMETRY%60%20before%20the%20import.%0A%0AThe%20package%20is%20listed%20as%20a%20%5BpeerDependency%20in%20%40better-auth/core%5D%28https%3A//github.com/better-auth/better-auth/blob/03278b5ad62c4cea61a8373bb7fe522519b31a42/packages/core/package.json%23L170%29%2C%20but%20when%20running%20via%20%60yarn%20dlx%60%2C%20peer%20dependencies%20aren%27t%20automatically%20installed%2C%20causing%20the%20%60ERR_MODULE_NOT_FOUND%60%20error.%0A%0A%2A%2APotential%20fixes%3A%2A%2A%0A1.%20Use%20a%20dynamic%20%60import%28%29%60%20with%20lazy%20loading%20when%20telemetry%20is%20actually%20needed%0A2.%20Move%20%60%40opentelemetry/api%60%20to%20regular%20dependencies%20%20%0A3.%20Wrap%20the%20import%20in%20a%20try-catch%20with%20a%20no-op%20fallback)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot?utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=join-discord)&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/8765)
Author
Owner

@mateusz-wojnar commented on GitHub (Mar 28, 2026):

any fix for that ?

<!-- gh-comment-id:4148159246 --> @mateusz-wojnar commented on GitHub (Mar 28, 2026): any fix for that ?
Author
Owner

@kvanbere commented on GitHub (Mar 28, 2026):

any fix for that ?

Alex @himself65 made a commit already, not sure status right now

In mean time, first post has workaround

<!-- gh-comment-id:4148886185 --> @kvanbere commented on GitHub (Mar 28, 2026): > any fix for that ? Alex @himself65 made a commit already, not sure status right now In mean time, first post has workaround
Author
Owner

@jonathansamines commented on GitHub (Apr 1, 2026):

Hey @mateusz-wojnar @kvanbere I think we generally expect peer dependencies to be auto-installed by your package manager of preference, and that is the case for most modern package managers. Truly optional peers are marked using optional peer dependencies

<!-- gh-comment-id:4173304704 --> @jonathansamines commented on GitHub (Apr 1, 2026): Hey @mateusz-wojnar @kvanbere I think we generally expect peer dependencies to be auto-installed by your package manager of preference, and that is the case for most modern package managers. Truly optional peers are marked using [`optional peer dependencies`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#peerdependenciesmeta)
Author
Owner

@kvanbere commented on GitHub (Apr 6, 2026):

Hey @mateusz-wojnar @kvanbere I think we generally expect peer dependencies to be auto-installed by your package manager of preference, and that is the case for most modern package managers. Truly optional peers are marked using optional peer dependencies

Hey @jonathansamines
Based on my research, there are two use cases:

  1. Certain features that require a dependency during import and don’t work at all (ie throw an exception) when a dependency is missing. These are not optional per-se, but you avoid the error if you don’t use the parts of the library or application that require these. These are non optional peer dependencies.

  2. Fully optional peer dependencies where the code conditionally imports the dependency and silently continues if it isn’t available.

In this case the telemetry is neither of these cases, it is a hard dependency that is imported the moment the CLI is run. Thus, it is a dependency, no different from the command line argument parser for example. The app just won’t run without it.

True, it may be a peer dependency in context of the Better Auth library, but for the CLI itself, it seems like it is actually a normal dependency because you cannot run it without this library. If you wanted it to be a peer dependency, then I can recommend embracing option (2) and adding a patch so that the telemetry silently disables without exception when the package isn’t available.

<!-- gh-comment-id:4195371696 --> @kvanbere commented on GitHub (Apr 6, 2026): > Hey [@mateusz-wojnar](https://github.com/mateusz-wojnar) [@kvanbere](https://github.com/kvanbere) I think we generally expect peer dependencies to be auto-installed by your package manager of preference, and that is the case for most modern package managers. Truly optional peers are marked using [`optional peer dependencies`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#peerdependenciesmeta) Hey @jonathansamines Based on my research, there are two use cases: 1. Certain features that require a dependency during import and don’t work at all (ie throw an exception) when a dependency is missing. These are not optional per-se, but you avoid the error if you don’t use the parts of the library or application that require these. These are non optional peer dependencies. 2. Fully optional peer dependencies where the code conditionally imports the dependency and silently continues if it isn’t available. In this case the telemetry is neither of these cases, it is a hard dependency that is imported the moment the CLI is run. Thus, it is a dependency, no different from the command line argument parser for example. The app just won’t run without it. True, it may be a peer dependency in context of the Better Auth library, but for the CLI itself, it seems like it is actually a normal dependency because you cannot run it without this library. If you wanted it to be a peer dependency, then I can recommend embracing option (2) and adding a patch so that the telemetry silently disables without exception when the package isn’t available.
Author
Owner

@kvanbere commented on GitHub (Apr 9, 2026):

Hey @jonathansamines turns out this isn't just the CLI tool, one of our devs is also getting this error now when running the server after upgrading to v1.6.2

In his .env file he has:

BETTER_AUTH_TELEMETRY=0

But when starting the server he is getting:

Could not resolve "@opentelemetry/api"
  
      node_modules/better-auth/node_modules/@better-auth/core/dist/instrumentation/tracer.mjs:2:38:
        2 │ import { SpanStatusCode, trace } from "@opentelemetry/api";

This is really disconcerting because with BETTER_AUTH_TELEMETRY=0 this shouldn't even be loading let alone pulled in as a dependency and added to the severs' module tree.

<!-- gh-comment-id:4218604055 --> @kvanbere commented on GitHub (Apr 9, 2026): Hey @jonathansamines turns out this isn't just the CLI tool, one of our devs is also getting this error now when running the server after upgrading to `v1.6.2` In his `.env` file he has: ``` BETTER_AUTH_TELEMETRY=0 ``` But when starting the server he is getting: ``` Could not resolve "@opentelemetry/api" node_modules/better-auth/node_modules/@better-auth/core/dist/instrumentation/tracer.mjs:2:38: 2 │ import { SpanStatusCode, trace } from "@opentelemetry/api"; ``` This is really disconcerting because with `BETTER_AUTH_TELEMETRY=0` this shouldn't even be loading let alone pulled in as a dependency and added to the severs' module tree.
Author
Owner

@bytaesu commented on GitHub (Apr 10, 2026):

https://github.com/better-auth/better-auth/pull/9086#issuecomment-4219581150

Can we resolve this while keeping it as a peer dependency? 🧐

<!-- gh-comment-id:4219590502 --> @bytaesu commented on GitHub (Apr 10, 2026): > https://github.com/better-auth/better-auth/pull/9086#issuecomment-4219581150 Can we resolve this while keeping it as a peer dependency? 🧐
Author
Owner

@kvanbere commented on GitHub (Apr 10, 2026):

That’s my preference too, to do this the solution would be to refactor telemetry to dynamically load the module and silently no-op if it fails.

<!-- gh-comment-id:4220174319 --> @kvanbere commented on GitHub (Apr 10, 2026): That’s my preference too, to do this the solution would be to refactor telemetry to dynamically load the module and silently no-op if it fails.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#19816