eyaltoledano/claude-task-master · error

projectRoot is required for getLocalBranches

Error message

projectRoot is required for getLocalBranches

What it means

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.

Source

Thrown at packages/tm-core/src/common/utils/git-utils.ts:99

	}

	try {
		const stdout = execSync('git rev-parse --abbrev-ref HEAD', {
			cwd: projectRoot,
			encoding: 'utf8'
		});
		return stdout.trim();
	} catch (error) {
		return null;
	}
}

/**
 * Get list of all local git branches
 */
export async function getLocalBranches(projectRoot: string): Promise<string[]> {
	if (!projectRoot) {
		throw new Error('projectRoot is required for getLocalBranches');
	}

	try {
		const { stdout } = await execAsync(
			'git branch --format="%(refname:short)"',
			{ cwd: projectRoot, maxBuffer: 10 * 1024 * 1024 }
		);
		return stdout
			.trim()
			.split('\n')
			.filter((branch) => branch.length > 0)
			.map((branch) => branch.trim());
	} catch (error) {
		return [];
	}
}

/**

View on GitHub (pinned to c0c98d367c)

Solutions

  1. Pass a valid non-empty directory path (the repo root or any directory inside the repo)
  2. Resolve the project root with fs/path before calling (path.resolve(process.cwd(), root))
  3. Fix the config/CLI layer that should populate projectRoot
  4. Guard at the call site to skip branch listing when root is unknown

Example fix

// before
const branches = await getLocalBranches('');
// after
const root = path.resolve(process.cwd(), projectRoot);
const branches = await getLocalBranches(root);
Defensive patterns

Strategy: validation

Validate before calling

import { statSync } from 'fs';
if (!projectRoot || !statSync(projectRoot, { throwIfNoEntry: false })?.isDirectory()) {
  throw new Error(`invalid projectRoot for branch listing: ${projectRoot}`);
}

Type guard

function isValidDir(v: unknown): v is string {
  return typeof v === 'string' && v.length > 0;
}

Try / catch

try {
  const branches = await getLocalBranches(projectRoot);
} catch (err) {
  if (err instanceof Error && err.message.includes('getLocalBranches')) {
    console.error('projectRoot missing; cannot list branches.');
    return [];
  }
  throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: Headless scripts where the project root option was omitted; tests constructing the utility without a fixture directory; upstream path resolution returning '' for nonexistent paths.

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29). Data as JSON: /api/errors/d2dfb55bea3b59cd. Report an issue: GitHub.