{"record":{"id":"243cbd9513bc5b78","repo":"vercel/turborepo","slug":"invalid-task-name-found-in-turbo-json","errorCode":null,"errorMessage":"Invalid task name found in turbo.json.","messagePattern":"Invalid task name found in turbo\\.json\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/eslint-plugin-turbo/lib/utils/calculate-inputs.ts","lineNumber":232,"sourceCode":"\nfunction environmentTestArray(envContext: EnvironmentTest) {\n  return [\n    envContext.legacyConfig,\n    envContext.env,\n    envContext.passThroughEnv,\n    envContext.dotEnv\n  ];\n}\n\n// Identify where to store `EnvironmentConfig`s\n\nfunction getTaskAddress(taskName: string): {\n  workspaceName: string | null;\n  scriptName: string;\n} {\n  // Somehow empty. Error.\n  if (taskName.length === 0) {\n    throw new Error(\"Invalid task name found in turbo.json.\");\n  }\n\n  const firstIndexOf = taskName.indexOf(\"#\");\n\n  // Something like \"build\"\n  if (firstIndexOf === -1) {\n    return {\n      workspaceName: null,\n      scriptName: taskName\n    };\n  }\n\n  // Something like \"what#are#you#doing\"\n  if (firstIndexOf !== taskName.lastIndexOf(\"#\")) {\n    throw new Error(\"Invalid task name found in turbo.json.\");\n  }\n\n  const [workspaceName, scriptName] = taskName.split(\"#\");","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/vercel/turborepo/blob/f9245100cf0d31d96628804ead485f6bf226e55a/packages/eslint-plugin-turbo/lib/utils/calculate-inputs.ts#L214-L250","documentation":"The eslint-plugin-turbo calculates task inputs by parsing task names from turbo.json. getTaskAddress splits each task key into an optional workspace name and a script name. It throws this Error when a task name is an empty string, because an empty key cannot address any task.","triggerScenarios":"A turbo.json contains an empty string as a task key, for example \"tasks\": { \"\": { ... } }. An empty segment can also appear when a key is produced by string splitting or config merging that yields an empty entry. getTaskAddress receives a zero-length taskName and throws.","commonSituations":"Hand-editing turbo.json and leaving an empty key. A codemod or script that generates task keys from a list with empty values. YAML to JSON conversion that turns a null key into an empty string.","solutions":["Open turbo.json, find the empty task key, and remove it","If the file is generated, fix the generator so it skips empty task names","Run ESLint again after saving the corrected file"],"exampleFix":"// before: turbo.json\n{ \"tasks\": { \"\": { \"outputs\": [\"dist/**\"] } } }\n// after: turbo.json\n{ \"tasks\": { \"build\": { \"outputs\": [\"dist/**\"] } } }","handlingStrategy":"validation","validationCode":"// scan turbo.json for empty task keys before running eslint-plugin-turbo\nimport fs from \"node:fs\";\n\nconst config = JSON.parse(fs.readFileSync(\"turbo.json\", \"utf8\"));\nconst tasks = config.tasks ?? config.pipeline ?? {};\nconst emptyKeys = Object.keys(tasks).filter((k) => k.length === 0);\nif (emptyKeys.length > 0) {\n  throw new Error(`Remove empty task keys from turbo.json: ${emptyKeys}`);\n}","typeGuard":"function isValidTaskName(name: string): boolean {\n  return name.length > 0;\n}","tryCatchPattern":null,"preventionTips":["Validate turbo.json keys in a pre-commit hook or CI lint step","Never generate task keys from unfiltered lists that may contain empty strings","Review diffs of turbo.json for stray empty keys after codemods"],"tags":["eslint-plugin-turbo","turbo-json","task-name","validation","linting"],"backgroundTag":"config-schema-validation","analyzedSha":"f9245100cf0d31d96628804ead485f6bf226e55a","analyzedAt":"2026-08-17T10:46:15.696Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}