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

mission-dir must be inside a git repository.

Error message

mission-dir must be inside a git repository.

What it means

ensurePathInside throws MISSION_DIR_GIT_ERROR ('mission-dir must be inside a git repository.') when the mission directory resolved by loadAutoresearchMissionContract is not contained within the repository root reported by git rev-parse --show-toplevel. This guards against mission dirs that escape the repo (absolute paths outside, or on a different filesystem branch).

Source

Thrown at src/autoresearch/contracts.ts:79

        ? err.stderr.toString('utf-8').trim()
        : '';
    throw contractError(stderr || MISSION_DIR_GIT_ERROR);
  }
}

export function slugifyMissionName(value: string): string {
  return value
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/-+/g, '-')
    .replace(/^-|-$/g, '')
    .slice(0, 48) || 'mission';
}

function ensurePathInside(parentPath: string, childPath: string): void {
  const rel = relative(parentPath, childPath);
  if (rel === '' || (!rel.startsWith('..') && rel !== '..')) return;
  throw contractError(MISSION_DIR_GIT_ERROR);
}

function extractFrontmatter(content: string): { frontmatter: string; body: string } {
  const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);
  if (!match) {
    throw contractError(SANDBOX_FRONTMATTER_ERROR);
  }
  return {
    frontmatter: match[1] || '',
    body: (match[2] || '').trim(),
  };
}

function parseSimpleYamlFrontmatter(frontmatter: string): Record<string, unknown> {
  const result: Record<string, unknown> = {};
  let currentSection: string | null = null;

  for (const rawLine of frontmatter.split(/\r?\n/)) {

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Move or copy the mission directory inside the git work tree and pass that path.
  2. Avoid symlinked mission dirs; pass the real path inside the repo.
  3. For worktrees/submodules, ensure the mission dir is inside the toplevel that git rev-parse --show-toplevel actually reports.
  4. Check for typos in the mission-dir argument that resolve to a path outside the repo.

Example fix

// before
await loadAutoresearchMissionContract('/elsewhere/missions/m1');

// after
await loadAutoresearchMissionContract('missions/m1'); // inside the repo root
Defensive patterns

Strategy: validation

Validate before calling

import { relative, resolve } from 'node:path';
import { execFile } from 'node:child_process';
import { promisify } from 'node:util';
const execFileAsync = promisify(execFile);

async function assertMissionInsideRepo(missionDir: string): Promise<void> {
  const { stdout } = await execFileAsync('git', ['-C', missionDir, 'rev-parse', '--show-toplevel']);
  const rel = relative(stdout.trim(), resolve(missionDir));
  if (rel === '' || rel.startsWith('..')) throw new Error('mission dir outside repo');
}

Try / catch

try {
  await loadAutoresearchMissionContract(dir);
} catch (err) {
  if ((err as Error).message.includes('inside a git repository')) {
    // move mission dir into the repo or fix symlink/worktree layout
  }
  throw err;
}

Prevention

When it happens

Trigger: readGit succeeds but the relative path from repoRoot to missionDir starts with '..' (or equals '..'), e.g. the mission dir is a sibling/parent of the repo root, a symlink pointing outside, or git reports a different toplevel than expected (worktree/submodule mismatch).

Common situations: Passing an absolute path to a mission folder that lies outside the repo; symlinks into the repo (git resolves the real toplevel, so the symlinked path computes as outside); mismatched submodule/worktree setups where the reported toplevel differs from the mission dir's location.

Related errors


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