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

mission.md is required inside mission-dir

Error message

mission.md is required inside mission-dir: ${missionFile}

What it means

loadAutoresearchMissionContract requires a mission.md file directly inside the mission directory; if existsSync(join(missionDir,'mission.md')) fails it throws with the expected file path. mission.md carries the mission instructions and is mandatory alongside sandbox.md.

Solutions

  1. Create mission.md inside the mission directory with the mission instructions.
  2. Check exact casing/spelling: it must be 'mission.md'.
  3. If templating missions, ensure the template includes both mission.md and sandbox.md.

Example fix

# before
missions/m1/
  sandbox.md

# after
missions/m1/
  mission.md
  sandbox.md
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync } from 'node:fs';
import { join } from 'node:path';

if (!existsSync(join(missionDir, 'mission.md'))) {
  throw new Error('mission.md missing — add mission instructions before loading');
}
const contract = await loadAutoresearchMissionContract(missionDir);

Try / catch

try {
  await loadAutoresearchMissionContract(dir);
} catch (err) {
  if ((err as Error).message.includes('mission.md is required')) {
    // create mission.md inside the mission dir (exact casing)
  }
  throw err;
}

Prevention

When it happens

Trigger: A mission directory that contains only sandbox.md (or other files) but no mission.md; wrong file name such as mission.txt or Mission.md on case-sensitive filesystems.

Common situations: Authoring a new mission and forgetting the instructions file; case-sensitivity issues on Linux after developing on macOS/Windows; renamed files during refactors.

Related errors


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

Appendix: source

Thrown at src/autoresearch/contracts.ts:224

  return {
    pass: result.pass,
    ...(result.score === undefined ? {} : { score: result.score }),
  };
}

export async function loadAutoresearchMissionContract(missionDirArg: string): Promise<AutoresearchMissionContract> {
  const missionDir = resolve(missionDirArg);
  if (!existsSync(missionDir)) {
    throw contractError(`mission-dir does not exist: ${missionDir}`);
  }

  const repoRoot = readGit(missionDir, ['rev-parse', '--show-toplevel']);
  ensurePathInside(repoRoot, missionDir);

  const missionFile = join(missionDir, 'mission.md');
  const sandboxFile = join(missionDir, 'sandbox.md');
  if (!existsSync(missionFile)) {
    throw contractError(`mission.md is required inside mission-dir: ${missionFile}`);
  }
  if (!existsSync(sandboxFile)) {
    throw contractError(`sandbox.md is required inside mission-dir: ${sandboxFile}`);
  }

  const missionContent = await readFile(missionFile, 'utf-8');
  const sandboxContent = await readFile(sandboxFile, 'utf-8');
  const sandbox = parseSandboxContract(sandboxContent);
  const missionRelativeDir = relative(repoRoot, missionDir) || basename(missionDir);
  const missionSlug = slugifyMissionName(missionRelativeDir);

  return {
    missionDir,
    repoRoot,
    missionFile,
    sandboxFile,
    missionRelativeDir,
    missionContent,

View on GitHub (pinned to 3ad79a8a6f)