The TypeScript compiler tsc is failing with TS6059: rootDir must contain all source files because it’s being asked to compile files that are outside the directory designated as the project’s root.

This error is usually a signal that your tsconfig.json is misconfigured, specifically with how rootDir and include (or files) interact, leading tsc to look for code in places it shouldn’t.

Here are the most common reasons this happens and how to fix them:

1. rootDir is Too Restrictive

Your rootDir setting might be too narrow, excluding files that are explicitly included in your compilation.

Diagnosis: Check your tsconfig.json. If rootDir is set to a specific subdirectory, like "rootDir": "./src", but your include or files directive points to files outside of ./src (e.g., "include": ["src/**/*.ts", "scripts/**/*.ts"]), you’ll hit this.

Fix: Broaden rootDir to encompass all directories listed in your include or files. A common and safe setting is to set rootDir to the project’s base directory.

{
  "compilerOptions": {
    "rootDir": "./", // Or your project's root directory
    // ... other options
  },
  "include": [
    "src/**/*.ts",
    "scripts/**/*.ts"
  ]
}

Why it works: By setting rootDir to "./", you’re telling the compiler that the entire project directory is the root. tsc then expects all files specified in include to reside within this root, which they now do.

2. include or files Points Outside rootDir

Conversely, your rootDir might be set correctly to the project root, but your include or files patterns are too broad, referencing files in locations that tsc mistakenly believes are outside the conceptual root it’s working with.

Diagnosis: Examine your tsconfig.json. If rootDir is "./" but your include contains patterns like "../shared/**/*.ts", this can cause issues if tsc isn’t interpreting the relative paths as intended within the project context.

Fix: Adjust your include patterns to only reference files within the project’s intended source tree. If you have shared code in a parent directory, it’s often better to symlink it into your src directory or adjust your build process to handle it separately. If it must be included, ensure rootDir is set high enough to contain all included files.

{
  "compilerOptions": {
    "rootDir": "./",
    // ...
  },
  "include": [
    "src/**/*.ts" // Only include files within the src directory
  ]
}

Why it works: This explicitly scopes the compilation to files within the src directory. If shared code is necessary, it should be made available within this scope.

3. Multiple tsconfig.json Files and Inheritance

If you have a complex project structure with multiple tsconfig.json files, especially using extends, the rootDir setting from a parent or inherited configuration might be too restrictive for a child configuration.

Diagnosis: Trace the extends chain in your tsconfig.json files. A rootDir defined in a base tsconfig.json might not be compatible with the include paths in a more specific child tsconfig.json.

Fix: Override or adjust rootDir in the child tsconfig.json to be more encompassing, or ensure the include patterns in the child are fully contained within the rootDir of the base configuration.

Example of overriding rootDir in a child tsconfig.json:

// tsconfig.base.json
{
  "compilerOptions": {
    "rootDir": "./src"
  }
}

// tsconfig.app.json (extends tsconfig.base.json)
{
  "extends": "./tsconfig.base.json",
  "compilerOptions": {
    "rootDir": "./" // Override to project root to include more files
  },
  "include": [
    "src/**/*.ts",
    "scripts/**/*.ts"
  ]
}

Why it works: By explicitly setting rootDir to "./" in tsconfig.app.json, you’re overriding the more restrictive setting from tsconfig.base.json to ensure that all files specified in tsconfig.app.json’s include are considered within the new root.

4. Incorrect baseUrl and Path Mappings

While baseUrl and paths are primarily for module resolution, misconfigurations here can sometimes indirectly influence how tsc interprets the project structure, especially when combined with rootDir.

Diagnosis: Review your baseUrl and paths in tsconfig.json. If you have complex path mappings that effectively pull code from outside the declared rootDir, tsc might get confused.

Fix: Ensure your baseUrl is set appropriately (often "./" or "./src") and that your paths mappings are consistent with your rootDir and include directives. Ideally, paths should map within the rootDir.

{
  "compilerOptions": {
    "baseUrl": "./",
    "rootDir": "./",
    "paths": {
      "@app/*": ["src/app/*"] // Mappings should point within rootDir
    }
    // ...
  },
  "include": ["src/**/*.ts"]
}

Why it works: This ensures that module resolution and file location interpretation are consistent. When baseUrl and paths are aligned with rootDir, tsc has a clearer understanding of the project’s file hierarchy.

5. Running tsc from the Wrong Directory

The rootDir is usually interpreted relative to the directory where tsconfig.json is located. If you’re running tsc from a different directory, the relative paths for rootDir and include can become ambiguous.

Diagnosis: Check the command you’re using to run tsc. Are you in the same directory as your tsconfig.json? Or are you using a command like tsc -p ./path/to/your/tsconfig.json from a different location?

Fix: Always run tsc from the root directory of your project where tsconfig.json resides, or use the -p flag to explicitly point to the correct tsconfig.json file from any directory.

# Assuming tsconfig.json is in the current directory
tsc

# Or from any directory, pointing to the tsconfig.json
tsc -p /path/to/your/project/tsconfig.json

Why it works: This ensures that all relative paths within tsconfig.json (like rootDir and include) are resolved correctly from the intended project root.

6. outDir Mismatch or Misconfiguration

While outDir doesn’t directly cause TS6059, a severely misconfigured outDir that implies a different project structure can sometimes lead to confusion or be a symptom of a broader structural misunderstanding that also affects rootDir.

Diagnosis: Look at your outDir setting. If it’s set to something like "../dist" and your rootDir is "./src", tsc might struggle to reconcile the source and output locations if not handled carefully.

Fix: Ensure outDir is set to a sensible location, typically a subdirectory like "./dist" or "./build", and that it’s distinct from rootDir.

{
  "compilerOptions": {
    "rootDir": "./src",
    "outDir": "./dist",
    // ...
  },
  "include": ["src/**/*.ts"]
}

Why it works: This clearly separates source and output directories, preventing tsc from inferring that output files should somehow be considered part of the source tree.

After addressing these, you might encounter a TS6042: Expression expected error if your tsconfig.json has a trailing comma that’s not supported by your Node.js version or the tsc parser.

Want structured learning?

Take the full Typescript course →