Fix: compilerOptions.paths Must Not Be Set (Alias Imports)
TypeScript

Fix: compilerOptions.paths Must Not Be Set (Alias Imports)

A tsconfig "paths" alias that works with the TypeScript compiler but breaks Create React App's build. Why CRA specifically forbids it, and three ways to keep clean "@/..." imports anyway.

Mahdi Ben RhoumaMahdi Ben Rhouma
7 min read
Fix: compilerOptions.paths Must Not Be Set (Alias Imports)

TL;DR#

compilerOptions.paths must not be set (alias imports are not supported) is thrown by Create React App's build-time config validator, not by the TypeScript compiler itself — CRA explicitly disallows the paths field in tsconfig.json because its Babel-based build has no mechanism to resolve the aliases it defines. Three fixes exist, from smallest change to full migration.

Why this only happens on Create React App#

The Stack Overflow question "compilerOptions.paths must not be set (alias imports are not supported)" has 38,000+ views because the setup that triggers it is common: add path aliases to tsconfig.json for cleaner imports, and the build fails outright.

json
// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": "src",
    "paths": {
      "@/*": ["*"]
    }
  }
}
text
Failed to compile.
 
The following changes are being made to your tsconfig.json file:
  - compilerOptions.paths must not be set (aliased imports are not supported)

The message is specific to react-scripts, the build tool behind Create React App. CRA compiles TypeScript by stripping types with Babel — it never runs the full TypeScript compiler as part of the build, only as a separate, parallel type-checking process. Babel has no concept of tsconfig.json's paths field; it transpiles each file independently without resolving module specifiers against a config map. If CRA silently allowed paths, import { Button } from '@/components/Button' would compile without error and then fail at runtime with a module-not-found error in the bundled output — so react-scripts fails loudly at build time instead, and (depending on version) may even rewrite your tsconfig.json to remove the field automatically.

Three ways to keep alias imports#

1. CRACO — the fix that doesn't eject#

CRACO (Create React App Configuration Override) lets you customize CRA's webpack config without running npm run eject, which is irreversible and hands you the full, unmaintained webpack config to own forever.

bash
npm install -D @craco/craco
js
// craco.config.js
const path = require('path');
 
module.exports = {
  webpack: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
    },
  },
};
json
// package.json — swap react-scripts for craco in the three build scripts
{
  "scripts": {
    "start": "craco start",
    "build": "craco build",
    "test": "craco test"
  }
}

Your tsconfig.json can keep paths for editor autocomplete and tsc --noEmit type-checking — CRACO's webpack alias is what actually resolves the import at bundle time, so both tools need the mapping defined, just in different files.

2. react-app-rewired#

An older, similarly-scoped alternative to CRACO, useful mainly if a project already depends on it:

bash
npm install -D react-app-rewired
js
// config-overrides.js
const path = require('path');
 
module.exports = function override(config) {
  config.resolve.alias = {
    ...config.resolve.alias,
    '@': path.resolve(__dirname, 'src'),
  };
  return config;
};

CRACO has broader plugin support and more active maintenance as of this writing; prefer it for a new setup.

3. Migrate off Create React App#

Create React App has had no new major release in years and no longer appears in React's own official "start a new app" recommendations. Both Vite and Next.js resolve tsconfig.json's paths natively — no CRACO, no config override, no eject:

json
// tsconfig.json — works as-is on Vite and Next.js, no extra tooling
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}

Vite additionally needs vite-tsconfig-paths if you're not using its React plugin's built-in resolution; Next.js resolves tsconfig.json paths out of the box with zero plugins, in both the App Router and Pages Router. If the project is a client-only SPA, Vite is the closer drop-in replacement for CRA; if it needs server rendering, API routes, or is already trending toward a full-stack app, migrating straight to Next.js avoids a second migration later. When moving off CRA, keep index.html at the project root: relocating it into src/ with a custom root is what produces Rollup failed to resolve import "/src/main.tsx".

Verifying the fix#

  1. After adding CRACO (or react-app-rewired), run a clean build (npm run build) — the specific "paths must not be set" error should be gone, and the build should complete.
  2. Import something through the alias in a component that wasn't previously using it, to confirm resolution works in the bundled build, not just in the editor (which resolves tsconfig.json paths independently via the TypeScript language server regardless of what the bundler does).
  3. Run tsc --noEmit separately — this checks types using the same tsconfig.json, and should already have been passing even before the alias config was fixed for the bundler, since tsc itself never rejected paths.

Further reading: Fix tsconfig Paths Not Working in Next.js, Force tsc to Ignore node_modules: Fix TS Errors.

One email a month — the latest explained errors

What the site published that month — mostly Next.js, Supabase and Node errors, explained. You confirm by email; unsubscribe any time in one click.

Frequently Asked Questions

|

Have more questions? Contact us

Still stuck? Paste your error.

Paste the error message or stack trace — we check it against every fix and tool on the site.

Matching happens in your browser. When you search, a cleaned error signature is sent so we can spot errors we do not cover yet — never the raw text, your IP address or your e-mail. Do not paste passwords or keys. Details

Written by

Mahdi Ben Rhouma
Mahdi Ben Rhouma

Full-Stack Dev — Next.js & Supabase

Solo developer building SaaS products with Next.js and Supabase. Writing about production patterns the official docs skip.

Remote