Skip to content
Latchkey

TypeScript "moduleResolution bundler" Errors - Fix Module Config in CI

moduleResolution: "bundler" tells tsc to resolve modules the way a bundler does (honoring exports, no mandatory extensions). It must be paired with a compatible module setting; mismatches raise TS5095, and switching from Node resolution can surface subpath-import errors.

What this error means

tsc fails with TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later, or previously-resolving subpath imports now error after switching moduleResolution to bundler.

tsc output
error TS5095: Option 'bundler' can only be used when 'module' is set to
'preserve' or to 'es2015' or later.
# or, after switching:
src/x.ts:2:23 - error TS2307: Cannot find module 'pkg/sub' or its
corresponding type declarations.

Diagnose it: which tsconfig and which compiler?

A TypeScript error that appears only in CI usually means the runner is compiling with a different config or a different compiler version than your editor. Your editor uses the workspace TypeScript and the nearest tsconfig.json; CI uses whatever the lockfile resolved and whatever config the build script names.

Terminal
# what CI will actually use
npx tsc --version
npx tsc --showConfig | head -40

# which files are in the program (a missing include is a common cause)
npx tsc --listFiles | wc -l

# type-check only, no emit, same as most CI gates
npx tsc --noEmit

Common causes

module not compatible with bundler resolution

moduleResolution: "bundler" requires module to be esnext/preserve/es2015+. A module: "commonjs" (or node16) paired with it triggers TS5095.

Resolution semantics changed from Node

bundler resolves exports maps and omitted extensions differently than node/node16. A subpath that resolved under one can fail under the other if the package's exports does not declare it.

How to fix it

Pair bundler with a compatible module setting

Set module to esnext/preserve when using moduleResolution: "bundler".

tsconfig.json
// tsconfig.json
{
  "compilerOptions": {
    "module": "esnext",
    "moduleResolution": "bundler"
  }
}

Fix subpath imports the exports map allows

  1. If a subpath import now fails, check the package's exports for that path.
  2. Import a path the exports map actually exposes, or use the package's documented entry.
  3. Keep tsc resolution aligned with how your bundler resolves at build time.

Pin the compiler so unrelated updates cannot break the gate

TypeScript adds errors in minor releases. An unpinned compiler turns a routine dependency update into a red build on code nobody touched, which is the most common false alarm in a TypeScript CI pipeline.

package.json
// package.json
{
  "devDependencies": {
    "typescript": "5.6.3"   // exact, not ^5.6.3
  }
}

How to prevent it

  • Match module to moduleResolution (bundler needs esnext/preserve).
  • Use bundler resolution only when a bundler does the loading.
  • Import only subpaths a package's exports map declares.

Frequently asked questions

What causes TypeScript "moduleResolution bundler" errors?
There are 2 common causes: module not compatible with bundler resolution and resolution semantics changed from node. moduleResolution: "bundler" requires module to be esnext/preserve/es2015+.
How do I fix TypeScript "moduleResolution bundler" errors?
There are 2 fixes depending on which cause you have: pair bundler with a compatible module setting and fix subpath imports the exports map allows. Work through them in order, since the first is the most common.
What does TypeScript "moduleResolution bundler" errors actually mean?
tsc fails with TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later, or previously-resolving subpath imports now error after switching moduleResolution to bundler.
How do I stop TypeScript "moduleResolution bundler" errors happening again?
Match module to moduleResolution (bundler needs esnext/preserve). The prevention section lists 3 changes that keep it from recurring.

Related guides

References

Not every red build is your code. Latchkey repairs the ones that are not, on the runner. Start free → 30-day trial · No credit card