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

sandbox.md must start with YAML frontmatter containing evalu

Error message

sandbox.md must start with YAML frontmatter containing evaluator.command and evaluator.format=json.

What it means

extractFrontmatter throws SANDBOX_FRONTMATTER_ERROR when sandbox.md content does not begin with a valid YAML frontmatter block: a leading '---' line, content, a closing '---' line. The regex /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/ requires the delimiters, so any deviation (missing fences, wrong characters, leading blank line/BOM) fails.

Source

Thrown at src/autoresearch/contracts.ts:85

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/)) {
    const line = rawLine.replace(/\t/g, '  ');
    const trimmed = line.trim();
    if (!trimmed || trimmed.startsWith('#')) continue;

    const sectionMatch = /^([A-Za-z0-9_-]+):\s*$/.exec(trimmed);
    if (sectionMatch) {

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Ensure sandbox.md starts on line 1 with exactly '---', then YAML, then a closing '---' line.
  2. Remove any BOM or blank lines before the first fence.
  3. Avoid trailing whitespace after the fence lines.
  4. Regenerate sandbox.md from a known-good template and re-apply changes.

Example fix

# before (sandbox.md)
This is my sandbox.
---
evaluator:
  command: ./run.sh
  format: json
---

# after
---
evaluator:
  command: ./run.sh
  format: json
---

This is my sandbox.
Defensive patterns

Strategy: validation

Validate before calling

function hasValidFrontmatter(content: string): boolean {
  return /^---\r?\n[\s\S]*?\r?\n---\r?(\n|$)/.test(content.charCodeAt(0) === 0xfeff ? content.slice(1) : content);
}

Type guard

const isFrontmatterDoc = (s: string): boolean => /^---\r?\n[\s\S]*?\r?\n---\r?(\n|$)/.test(s);

Try / catch

try {
  const parsed = parseSandboxContract(content);
} catch (err) {
  if ((err as Error).message.includes('must start with YAML frontmatter')) {
    // rewrite file with leading --- fences or strip BOM
  }
  throw err;
}

Prevention

When it happens

Trigger: parseSandboxContract receives sandbox.md content that does not start with '---\n' or lacks a closing '---' line — e.g. the file starts with prose, has a BOM or blank line before the first fence, or uses '---' with trailing spaces.

Common situations: Hand-editing sandbox.md and deleting a fence; editors saving with a BOM; copying the file from docs that stripped the leading '---'; CRLF/whitespace issues around the fences.

Related errors


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