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

stderr || `git ${args.join(' ')} failed`

Error message

stderr || `git ${args.join(' ')} failed`

What it means

readGit wraps git subprocess execution and rethrows with the git command's trimmed stderr (or a generic 'git <args> failed' message when stderr is empty). It surfaces any failure of an async git invocation, such as rev-parse, branch lookups, or path exclusions.

Source

Thrown at src/autoresearch/runtime.ts:175

  return trimmed.length <= max ? trimmed : `${trimmed.slice(0, max)}\n...`;
}

function readGit(repoPath: string, args: string[]): string {
  try {
    return execFileSync('git', args, {
      cwd: repoPath,
      encoding: 'utf-8',
      stdio: ['ignore', 'pipe', 'pipe'],
      windowsHide: true,
    }).trim();
  } catch (error) {
    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 tryResolveGitCommit(worktreePath: string, ref: string): string | null {
  const result = spawnSync('git', ['rev-parse', '--verify', `${ref}^{commit}`], {
    cwd: worktreePath,
    encoding: 'utf-8',
  });
  if (result.status !== 0) return null;
  const resolved = (result.stdout || '').trim();
  return resolved || null;
}

async function writeGitInfoExclude(worktreePath: string, pattern: string): Promise<void> {
  const excludePath = readGit(worktreePath, ['rev-parse', '--git-path', 'info/exclude']);
  const existing = existsSync(excludePath)
    ? await readFile(excludePath, 'utf-8')
    : '';

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Run the printed git command manually in the same cwd to see the real failure
  2. Verify the working directory is a valid git repository and the ref/commit exists (git rev-parse <ref>)
  3. Check git is installed and on PATH in the execution environment (CI containers, nix shells)
  4. For auth failures in CI, configure credentials or run with a token that can read the repo

Example fix

// before
const head = await readGit(repoRoot, ['rev-parse', 'HEAD']); // throws 'unknown revision...'
// after
// ensure repo has at least one commit
await run('git', ['commit', '--allow-empty', '-m', 'init'], { cwd: repoRoot });
const head = await readGit(repoRoot, ['rev-parse', 'HEAD']);
Defensive patterns

Strategy: try-catch

Validate before calling

import { spawnSync } from 'node:child_process';
function gitAvailable(cwd: string): boolean {
  return spawnSync('git', ['rev-parse', '--is-inside-work-tree'], { cwd }).status === 0;
}

Try / catch

try { const sha = await readGit(cwd, ['rev-parse', 'HEAD']); }
catch (e) { if (e instanceof Error && /git .* failed|fatal:/.test(e.message)) { /* surface git stderr, validate repo state */ } throw e; }

Prevention

When it happens

Trigger: Any async git invocation failing: missing ref/commit (rev-parse on an unknown SHA), detached/missing branch, not inside a git repository, git not on PATH for the async execution environment, or permission problems on the repo.

Common situations: Running autoresearch in a directory that is not a git worktree, referencing a commit that was garbage-collected, shallow clones missing expected history, or CI environments where git auth/config blocks the command.

Related errors


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