{"record":{"id":"d2dfb55bea3b59cd","repo":"eyaltoledano/claude-task-master","slug":"projectroot-is-required-for-getlocalbranches","errorCode":null,"errorMessage":"projectRoot is required for getLocalBranches","messagePattern":"projectRoot is required for getLocalBranches","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/tm-core/src/common/utils/git-utils.ts","lineNumber":99,"sourceCode":"\t}\n\n\ttry {\n\t\tconst stdout = execSync('git rev-parse --abbrev-ref HEAD', {\n\t\t\tcwd: projectRoot,\n\t\t\tencoding: 'utf8'\n\t\t});\n\t\treturn stdout.trim();\n\t} catch (error) {\n\t\treturn null;\n\t}\n}\n\n/**\n * Get list of all local git branches\n */\nexport async function getLocalBranches(projectRoot: string): Promise<string[]> {\n\tif (!projectRoot) {\n\t\tthrow new Error('projectRoot is required for getLocalBranches');\n\t}\n\n\ttry {\n\t\tconst { stdout } = await execAsync(\n\t\t\t'git branch --format=\"%(refname:short)\"',\n\t\t\t{ cwd: projectRoot, maxBuffer: 10 * 1024 * 1024 }\n\t\t);\n\t\treturn stdout\n\t\t\t.trim()\n\t\t\t.split('\\n')\n\t\t\t.filter((branch) => branch.length > 0)\n\t\t\t.map((branch) => branch.trim());\n\t} catch (error) {\n\t\treturn [];\n\t}\n}\n\n/**","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/packages/tm-core/src/common/utils/git-utils.ts#L81-L117","documentation":"getLocalBranches lists branches via 'git branch --format=\"%(refname:short)\"' run in projectRoot. An empty projectRoot cannot serve as a working directory, so the guard throws this error immediately. It is a fail-fast argument check.","triggerScenarios":"Calling getLocalBranches(undefined) or '' — typically an unresolved project root passed straight through from config or CLI parsing; also via the branches wrapper with an empty root.","commonSituations":"Headless scripts where the project root option was omitted; tests constructing the utility without a fixture directory; upstream path resolution returning '' for nonexistent paths.","solutions":["Pass a valid non-empty directory path (the repo root or any directory inside the repo)","Resolve the project root with fs/path before calling (path.resolve(process.cwd(), root))","Fix the config/CLI layer that should populate projectRoot","Guard at the call site to skip branch listing when root is unknown"],"exampleFix":"// before\nconst branches = await getLocalBranches('');\n// after\nconst root = path.resolve(process.cwd(), projectRoot);\nconst branches = await getLocalBranches(root);","handlingStrategy":"validation","validationCode":"import { statSync } from 'fs';\nif (!projectRoot || !statSync(projectRoot, { throwIfNoEntry: false })?.isDirectory()) {\n  throw new Error(`invalid projectRoot for branch listing: ${projectRoot}`);\n}","typeGuard":"function isValidDir(v: unknown): v is string {\n  return typeof v === 'string' && v.length > 0;\n}","tryCatchPattern":"try {\n  const branches = await getLocalBranches(projectRoot);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('getLocalBranches')) {\n    console.error('projectRoot missing; cannot list branches.');\n    return [];\n  }\n  throw err;\n}","preventionTips":["Pass the same resolved root constant to all git-utils calls","Sanity-check root exists on disk before git operations","Fail fast at CLI arg parsing when --project-root is required but absent","Cover branch-listing paths in tests with explicit repo fixtures"],"tags":["git","argument-validation"],"backgroundTag":"missing-required-parameter","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}