vercel/turborepo · error · Error

Found both turbo.json and turbo.jsonc in the same directory:

Error message

Found both turbo.json and turbo.jsonc in the same directory: ${dirPath}
Please use either turbo.json or turbo.jsonc, but not both.

What it means

getWorkspaceConfigs() resolves each workspace's turbo config via resolveTurboConfigPath(); when that resolver detects both turbo.json and turbo.jsonc in the same workspace directory it returns an error string, which this code logs and rethrows. Same root cause as the getTurboConfigs() variant, but hit while enumerating workspaces during package.json discovery (editor tooling, turbo gen, workspace introspection).

Source

Thrown at packages/turbo-utils/src/get-turbo-configs.ts:288

        const workspaceName = packageJsonContent.name;
        const workspacePath = path.dirname(configPath);
        const isWorkspaceRoot = workspacePath === turboRoot;

        // Try and get turbo.json or turbo.jsonc
        const {
          configPath: turboConfigPath,
          configExists,
          error
        } = resolveTurboConfigPath(workspacePath);

        let rawTurboJson = null;
        let turboConfig: SchemaV1 | undefined;

        try {
          if (error) {
            logger.error(error);
            throw new Error(error);
          }

          if (configExists && turboConfigPath) {
            rawTurboJson = fs.readFileSync(turboConfigPath, "utf8");
          }

          if (rawTurboJson) {
            turboConfig = JSON5.parse(rawTurboJson);

            if (turboConfig) {
              // basic config validation
              if (isWorkspaceRoot) {
                // invalid - root config with extends
                if ("extends" in turboConfig) {
                  continue;
                }
              } else if (!("extends" in turboConfig)) {
                // invalid - workspace config with no extends

View on GitHub (pinned to 9f94a7d215)

Solutions

  1. In the offending workspace directory, remove either turbo.json or turbo.jsonc so only one exists
  2. Merge any differing settings into the file you keep before deleting the other
  3. Add a repo lint/grep in CI to catch duplicated turbo configs

Example fix

# before
ls apps/web # => turbo.json turbo.jsonc

# after
git rm apps/web/turbo.json # keep turbo.jsonc
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync } from "node:fs";
import path from "node:path";

const dirs = workspacePaths; // from package.json discovery
const conflicts = dirs.filter(
  (d) => existsSync(path.join(d, "turbo.json")) && existsSync(path.join(d, "turbo.jsonc"))
);
if (conflicts.length) throw new Error(`Conflicting turbo configs in: ${conflicts.join(", ")}`);

Try / catch

try {
  getWorkspaceConfigs(cwd);
} catch (e) {
  if (e instanceof Error && e.message.includes("Found both turbo.json and turbo.jsonc")) {
    // the message names the directory; remove one file and retry
  } else throw e;
}

Prevention

When it happens

Trigger: A workspace directory containing both turbo.json and turbo.jsonc, encountered while getWorkspaceConfigs() iterates every workspace package.json under the turbo root.

Common situations: IDE/LSP or generator runs failing after a partial migration to .jsonc; generated workspaces containing a stale turbo.json next to a hand-written turbo.jsonc.

Related errors


AI-assisted analysis of vercel/turborepo@9f94a7d215 (2026-08-16). Data as JSON: /api/errors/0ab9cb6c6ba7a7b7. Report an issue: GitHub.