Yeachan-Heo/oh-my-codex · error · Error

invalid_worktree_branch

invalid_worktree_branch

Error message

invalid_worktree_branch:${branchName}

What it means

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.

Source

Thrown at src/team/worktree.ts:112

    const err = error as NodeJS.ErrnoException & { stderr?: string | Buffer };
    const stderr = typeof err.stderr === 'string'
      ? err.stderr.trim()
      : err.stderr instanceof Buffer
        ? err.stderr.toString('utf-8').trim()
        : '';
    throw new Error(stderr || `git ${args.join(' ')} failed`);
  }
}

function validateBranchName(repoRoot: string, branchName: string): void {
  const result = spawnSync('git', ['check-ref-format', '--branch', branchName], {
    cwd: repoRoot,
    encoding: 'utf-8',
      windowsHide: true,
    });
  if (result.status === 0) return;
  const stderr = (result.stderr || '').trim();
  throw new Error(stderr || `invalid_worktree_branch:${branchName}`);
}

function branchExists(repoRoot: string, branchName: string): boolean {
  const result = spawnSync('git', ['show-ref', '--verify', '--quiet', `refs/heads/${branchName}`], {
    cwd: repoRoot,
    encoding: 'utf-8',
  });
  return result.status === 0;
}

export function isWorktreeDirty(worktreePath: string): boolean {
  const result = spawnSync('git', ['status', '--porcelain'], {
    cwd: worktreePath,
    encoding: 'utf-8',
      windowsHide: true,
    });
  if (result.status !== 0) {
    const stderr = (result.stderr || '').trim();

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Sanitize the branch name (and its components) with a token sanitizer, e.g. strip to [A-Za-z0-9._-], before calling the planner
  2. Check the composed name yourself with `git check-ref-format --branch <name>` and fail fast with a clear message
  3. Verify git is installed and on PATH (spawnSync('git',['--version'])) at startup
  4. If the name comes from user input, reject it early with a validation error instead of letting git validation throw

Example fix

// before
const branch = `${mode.name}/${workerName}`; // workerName = "john doe"
planWorktreeTarget({ branchName: branch, ... });

// after
const sanitize = (s: string) => s.trim().replace(/[^A-Za-z0-9._-]+/g, '-');
const branch = `${sanitize(mode.name)}/${sanitize(workerName)}`;
planWorktreeTarget({ branchName: branch, ... });
Defensive patterns

Strategy: validation

Validate before calling

import { spawnSync } from 'node:child_process';

function isValidBranchName(name: string): boolean {
  if (!name || /[\s~^:?*[\]\\]/.test(name) || name.includes('..') ||
      name.startsWith('-') || name.endsWith('.lock') || name.endsWith('/') || name.endsWith('.')) return false;
  return spawnSync('git', ['check-ref-format', `refs/heads/${name}`], { encoding: 'utf-8' }).status === 0;
}

const ok = isValidBranchName(branch);

Type guard

function isSafeBranchToken(s: unknown): s is string {
  return typeof s === 'string' && /^[A-Za-z0-9._-]+$/.test(s) && !s.endsWith('.lock');
}

Try / catch

catch (e) { if (String(e?.message).startsWith('invalid_worktree_branch:')) { /* sanitize name or prompt user */ } else throw e; }

Prevention

When it happens

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

Common situations: 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`.

Related errors


AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27). Data as JSON: /api/errors/4fdd1e8d5216accd. Report an issue: GitHub.