{"record":{"id":"aac2d3a698120912","repo":"vercel/turborepo","slug":"may-not-specify-workspace-name-in-non-root-turbo-j","errorCode":null,"errorMessage":"May not specify workspace name in non-root turbo.json","messagePattern":"May not specify workspace name in non-root turbo\\.json","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/eslint-plugin-turbo/lib/utils/calculate-inputs.ts","lineNumber":363,"sourceCode":"              taskDefinition\n            );\n          }\n        }\n      );\n    }\n\n    for (const projectWorkspace of this.projectWorkspaces) {\n      if (!projectWorkspace.turboConfig) {\n        continue;\n      }\n\n      forEachTaskDef(\n        projectWorkspace.turboConfig,\n        ([taskName, taskDefinition]) => {\n          const { workspaceName: erroneousWorkspaceName, scriptName } =\n            getTaskAddress(taskName);\n          if (erroneousWorkspaceName) {\n            throw new Error(\n              \"May not specify workspace name in non-root turbo.json\"\n            );\n          }\n\n          const workspaceName = projectWorkspace.workspaceName;\n          workspaceTasks[workspaceName] =\n            workspaceName in workspaceTasks\n              ? workspaceTasks[workspaceName]\n              : {};\n          workspaceTasks[workspaceName][scriptName] = processTask(\n            projectWorkspace.workspacePath,\n            taskDefinition\n          );\n        }\n      );\n    }\n\n    return {","sourceCodeStart":345,"sourceCodeEnd":381,"githubUrl":"https://github.com/vercel/turborepo/blob/f9245100cf0d31d96628804ead485f6bf226e55a/packages/eslint-plugin-turbo/lib/utils/calculate-inputs.ts#L345-L381","documentation":"eslint-plugin-turbo walks every workspace-level turbo.json and registers each task under that workspace. The \"workspace#task\" key syntax is only valid in the root turbo.json. This Error is thrown when a non-root turbo.json uses a workspace-qualified task name, because the plugin would store the task under the wrong workspace.","triggerScenarios":"A file like packages/web/turbo.json contains a key such as \"web#build\". The plugin iterates projectWorkspaces, calls getTaskAddress on the key, sees a non-null workspaceName inside a workspace-level config, and throws.","commonSituations":"Copying a root turbo.json into a package without stripping the workspace prefixes. Following an example that mixes root and workspace syntax. Applying a codemod that prefixes all task keys with the package name.","solutions":["Open the workspace-level turbo.json named in the error and remove the \"workspace#\" prefix from every task key","If you need a workspace-specific override of another workspace's task, put it in the root turbo.json where qualified names are allowed","Re-run ESLint to confirm the plugin accepts the file"],"exampleFix":"// before: packages/web/turbo.json\n{ \"extends\": [\"//\"], \"tasks\": { \"web#build\": { \"outputs\": [\"dist/**\"] } } }\n// after: packages/web/turbo.json\n{ \"extends\": [\"//\"], \"tasks\": { \"build\": { \"outputs\": [\"dist/**\"] } } }","handlingStrategy":"validation","validationCode":"// ensure workspace-level turbo.json files use unqualified task names\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nfor (const ws of workspaceDirs) {\n  const p = path.join(ws, \"turbo.json\");\n  if (!fs.existsSync(p)) continue;\n  const tasks = JSON.parse(fs.readFileSync(p, \"utf8\")).tasks ?? {};\n  const qualified = Object.keys(tasks).filter((k) => k.includes(\"#\"));\n  if (qualified.length > 0) {\n    throw new Error(`${p}: remove workspace qualifiers from ${qualified}`);\n  }\n}","typeGuard":"function isAllowedInWorkspaceConfig(key: string): boolean {\n  return !key.includes(\"#\");\n}","tryCatchPattern":null,"preventionTips":["Keep workspace-qualified task keys only in the root turbo.json","Use the extends: [\"//\"] convention in workspace turbo.json files","Review copied root configs before placing them in packages"],"tags":["eslint-plugin-turbo","turbo-json","workspace","config","validation"],"backgroundTag":"config-schema-validation","analyzedSha":"f9245100cf0d31d96628804ead485f6bf226e55a","analyzedAt":"2026-08-17T10:46:15.696Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}