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 extendsView on GitHub (pinned to 9f94a7d215)
Solutions
- In the offending workspace directory, remove either turbo.json or turbo.jsonc so only one exists
- Merge any differing settings into the file you keep before deleting the other
- 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
- During .jsonc migrations, git rm the old file atomically with adding the new one
- Run `find . \( -name turbo.json -o -name turbo.jsonc \)` before pushing workspace changes
- Codemods that write turbo.json should first check for an existing turbo.jsonc
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
- Found both turbo.json and turbo.jsonc in the same directory:
- Invalid task name found in turbo.json.
- May not specify workspace name in non-root turbo.json
- No config at "${configPath}"
- Unable to load generators
AI-assisted analysis of vercel/turborepo@9f94a7d215 (2026-08-16).
Data as JSON: /api/errors/0ab9cb6c6ba7a7b7.
Report an issue: GitHub.