{"record":{"id":"4fdd1e8d5216accd","repo":"Yeachan-Heo/oh-my-codex","slug":"invalid-worktree-branch","errorCode":"invalid_worktree_branch","errorMessage":"invalid_worktree_branch:${branchName}","messagePattern":"invalid_worktree_branch:(.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/team/worktree.ts","lineNumber":112,"sourceCode":"    const err = error as NodeJS.ErrnoException & { stderr?: string | Buffer };\n    const stderr = typeof err.stderr === 'string'\n      ? err.stderr.trim()\n      : err.stderr instanceof Buffer\n        ? err.stderr.toString('utf-8').trim()\n        : '';\n    throw new Error(stderr || `git ${args.join(' ')} failed`);\n  }\n}\n\nfunction validateBranchName(repoRoot: string, branchName: string): void {\n  const result = spawnSync('git', ['check-ref-format', '--branch', branchName], {\n    cwd: repoRoot,\n    encoding: 'utf-8',\n      windowsHide: true,\n    });\n  if (result.status === 0) return;\n  const stderr = (result.stderr || '').trim();\n  throw new Error(stderr || `invalid_worktree_branch:${branchName}`);\n}\n\nfunction branchExists(repoRoot: string, branchName: string): boolean {\n  const result = spawnSync('git', ['show-ref', '--verify', '--quiet', `refs/heads/${branchName}`], {\n    cwd: repoRoot,\n    encoding: 'utf-8',\n  });\n  return result.status === 0;\n}\n\nexport function isWorktreeDirty(worktreePath: string): boolean {\n  const result = spawnSync('git', ['status', '--porcelain'], {\n    cwd: worktreePath,\n    encoding: 'utf-8',\n      windowsHide: true,\n    });\n  if (result.status !== 0) {\n    const stderr = (result.stderr || '').trim();","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/team/worktree.ts#L94-L130","documentation":"Thrown when `git rev-parse --verify` for a planned branch name exits non-zero with no stderr, meaning the branch name is syntactically invalid or unverifiable as a git ref. The library validates the branch name before creating a worktree so that `git worktree add` doesn't fail later with a confusing error. The message embeds the offending branch name.","triggerScenarios":"Calling planWorktreeTarget/ensureWorktree with a branch name containing invalid ref characters (spaces, `..`, `~`, `^`, `:`, `?`, `*`, `[`, leading `-`, or trailing `.lock`), or a name that git refuses to resolve. Also occurs if the git spawn itself fails silently (git not installed) leaving empty stderr.","commonSituations":"Worker names or team names with spaces or slashes injected into branch names like `${mode.name}/${workerName}`; unicode/emoji in worker names; git missing from PATH so stderr is empty; names ending in `.lock`.","solutions":["Sanitize the branch name (and its components) with a token sanitizer, e.g. strip to [A-Za-z0-9._-], before calling the planner","Check the composed name yourself with `git check-ref-format --branch <name>` and fail fast with a clear message","Verify git is installed and on PATH (spawnSync('git',['--version'])) at startup","If the name comes from user input, reject it early with a validation error instead of letting git validation throw"],"exampleFix":"// before\nconst branch = `${mode.name}/${workerName}`; // workerName = \"john doe\"\nplanWorktreeTarget({ branchName: branch, ... });\n\n// after\nconst sanitize = (s: string) => s.trim().replace(/[^A-Za-z0-9._-]+/g, '-');\nconst branch = `${sanitize(mode.name)}/${sanitize(workerName)}`;\nplanWorktreeTarget({ branchName: branch, ... });","handlingStrategy":"validation","validationCode":"import { spawnSync } from 'node:child_process';\n\nfunction isValidBranchName(name: string): boolean {\n  if (!name || /[\\s~^:?*[\\]\\\\]/.test(name) || name.includes('..') ||\n      name.startsWith('-') || name.endsWith('.lock') || name.endsWith('/') || name.endsWith('.')) return false;\n  return spawnSync('git', ['check-ref-format', `refs/heads/${name}`], { encoding: 'utf-8' }).status === 0;\n}\n\nconst ok = isValidBranchName(branch);","typeGuard":"function isSafeBranchToken(s: unknown): s is string {\n  return typeof s === 'string' && /^[A-Za-z0-9._-]+$/.test(s) && !s.endsWith('.lock');\n}","tryCatchPattern":"catch (e) { if (String(e?.message).startsWith('invalid_worktree_branch:')) { /* sanitize name or prompt user */ } else throw e; }","preventionTips":["Sanitize all user-supplied components of branch names (worker, team, mode) to [A-Za-z0-9._-]","Verify git is on PATH at startup before planning worktrees","Add unit tests for branch-name composition with hostile inputs (spaces, unicode, '.lock')"],"tags":["git","worktree","branch-name","validation"],"backgroundTag":"invalid-git-ref-name","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}