{"record":{"id":"44cb3ba886d3e8ff","repo":"eyaltoledano/claude-task-master","slug":"projectroot-is-required-for-getdefaultbranch","errorCode":null,"errorMessage":"projectRoot is required for getDefaultBranch","messagePattern":"projectRoot is required for getDefaultBranch","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/tm-core/src/common/utils/git-utils.ts","lineNumber":204,"sourceCode":"\n\ttry {\n\t\tconst { stdout } = await execAsync('git rev-parse --show-toplevel', {\n\t\t\tcwd: projectRoot\n\t\t});\n\t\treturn stdout.trim();\n\t} catch (error) {\n\t\treturn null;\n\t}\n}\n\n/**\n * Get the default branch name for the repository\n */\nexport async function getDefaultBranch(\n\tprojectRoot: string\n): Promise<string | null> {\n\tif (!projectRoot) {\n\t\tthrow new Error('projectRoot is required for getDefaultBranch');\n\t}\n\n\ttry {\n\t\t// Try to get from GitHub first (if gh CLI is available)\n\t\tif (await isGhCliAvailable(projectRoot)) {\n\t\t\tconst repoInfo = await getGitHubRepoInfo(projectRoot);\n\t\t\tif (repoInfo && repoInfo.defaultBranchRef) {\n\t\t\t\treturn repoInfo.defaultBranchRef.name;\n\t\t\t}\n\t\t}\n\n\t\t// Fallback to git remote info (support non-origin remotes)\n\t\tconst remotesRaw = await execAsync('git remote', { cwd: projectRoot });\n\t\tconst remotes = remotesRaw.stdout.trim().split('\\n').filter(Boolean);\n\t\tif (remotes.length > 0) {\n\t\t\tconst primary = remotes.includes('origin') ? 'origin' : remotes[0];\n\t\t\t// Parse `git remote show` (preferred)\n\t\t\ttry {","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/packages/tm-core/src/common/utils/git-utils.ts#L186-L222","documentation":"getDefaultBranch resolves the repository's default branch, first via gh CLI/GitHub info and falling back to git symbolic-ref, executing in projectRoot. An empty projectRoot is rejected by the guard before any command runs. It is a fail-fast argument check for a function usually reached through currentBranch/defaultBranch helpers.","triggerScenarios":"Calling getDefaultBranch(undefined) or ''; also triggered indirectly when isOnDefaultBranch or wrapper helpers forward an empty root.","commonSituations":"Automation where the project root option is optional and unset; tests stubbing config with partial objects; downstream propagation of an earlier failed root lookup.","solutions":["Pass a valid repository path: getDefaultBranch('/path/to/project')","Default to process.cwd() at the call site","Repair config/CLI parsing so projectRoot is always populated","Guard upstream helpers to short-circuit with null when root is missing"],"exampleFix":"// before\nconst def = await getDefaultBranch(root); // root undefined\n// after\nconst def = root ? await getDefaultBranch(root) : null;","handlingStrategy":"validation","validationCode":"if (!projectRoot || typeof projectRoot !== 'string') {\n  throw new Error('getDefaultBranch needs a valid projectRoot');\n}\n// then handle both null (unknown default) and a value:\nconst defaultBranch = await getDefaultBranch(projectRoot);","typeGuard":"function isNonEmptyRoot(v: unknown): v is string {\n  return typeof v === 'string' && v.length > 0;\n}","tryCatchPattern":"try {\n  const def = await getDefaultBranch(projectRoot);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('getDefaultBranch')) {\n    console.error('projectRoot missing; assuming \"main\".');\n    return 'main';\n  }\n  throw err;\n}","preventionTips":["Fall back to 'main'/'master' heuristics only after root validation succeeds","Resolve projectRoot before any default-branch logic in scripts","Keep root resolution in one shared utility to avoid '' leaking through wrappers","Write tests that call getDefaultBranch with a real repo fixture"],"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"}