TypeScript "paths"/"baseUrl" Alias Not Resolving - Fix tsconfig in CI
A paths alias (@/*) that works in your editor can fail in CI when baseUrl is missing, when paths are defined in a base tsconfig that the project does not correctly extend, or when the bundler/runtime has no matching alias of its own.
What this error means
tsc reports TS2307: Cannot find module '@/...' in CI even though the editor resolves it, or the type-check passes but the runtime/bundler fails on the same alias. It is deterministic and tied to config inheritance.
src/app/page.tsx:2:20 - error TS2307: Cannot find module '@/lib/api' or
its corresponding type declarations.
2 import { api } from '@/lib/api'
~~~~~~~~~~~Common causes
baseUrl missing or paths not inherited
Older TypeScript requires baseUrl for paths to resolve. If paths live in an extended base config, the relative resolution can break unless the extending project re-declares them or uses the right relative roots.
Bundler/runtime lacks the matching alias
tsc paths only teach the type-checker. The bundler (Webpack resolve.alias, Vite resolve.alias) or Node runtime needs its own alias, or the alias resolves at type-check time but fails at build/run time.
How to fix it
Declare baseUrl and paths in the project tsconfig
Define both so resolution does not depend on inheritance quirks.
// tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": { "@/*": ["src/*"] }
}
}Give the bundler the same alias
Mirror the tsconfig alias in the bundler (or derive it) so build/runtime resolution matches.
// vite.config.ts (or use vite-tsconfig-paths to derive from tsconfig)
resolve: { alias: { '@': '/src' } }How to prevent it
- Declare
baseUrl+pathsin the project tsconfig, not only a base config. - Keep bundler/runtime aliases in sync with tsconfig
paths(or derive them). - Run
tsc --noEmitand the real build in CI so editor-only resolution gaps fail.