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

Invalid sandbox.md frontmatter section: ${currentSection}

Error message

Invalid sandbox.md frontmatter section: ${currentSection}

What it means

parseSimpleYamlFrontmatter throws when an indented key targets a currentSection that does not hold a plain object — i.e. the section name was previously assigned a scalar or an array. Since the parser stores top-level 'key: value' as strings, trying to nest under such a key (or under an array-valued entry) is invalid in its one-level model.

Source

Thrown at src/autoresearch/contracts.ts:122

      currentSection = sectionMatch[1];
      result[currentSection] = {};
      continue;
    }

    const nestedMatch = /^([A-Za-z0-9_-]+):\s*(.+)\s*$/.exec(trimmed);
    if (!nestedMatch) {
      throw contractError(`Unsupported sandbox.md frontmatter line: ${trimmed}`);
    }

    const [, key, rawValue] = nestedMatch;
    const value = rawValue.replace(/^['"]|['"]$/g, '');
    if (line.startsWith(' ') || line.startsWith('\t')) {
      if (!currentSection) {
        throw contractError(`Nested sandbox.md frontmatter key requires a parent section: ${trimmed}`);
      }
      const section = result[currentSection];
      if (!section || typeof section !== 'object' || Array.isArray(section)) {
        throw contractError(`Invalid sandbox.md frontmatter section: ${currentSection}`);
      }
      (section as Record<string, unknown>)[key] = value;
      continue;
    }

    result[key] = value;
    currentSection = null;
  }

  return result;
}

function parseKeepPolicy(raw: unknown): AutoresearchKeepPolicy | undefined {
  if (raw === undefined) return undefined;
  if (typeof raw !== 'string') {
    throw contractError('sandbox.md frontmatter evaluator.keep_policy must be a string when provided.');
  }
  const normalized = raw.trim().toLowerCase();

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Make section headers bare ('evaluator:' with no inline value) before nested keys.
  2. Remove duplicate keys that assign scalars to names used as sections.
  3. Keep values either a flat scalar at top level or a one-level nested block — not both.

Example fix

# before
evaluator: run
evaluator:
  command: ./run.sh

# after
evaluator:
  command: ./run.sh
Defensive patterns

Strategy: validation

Validate before calling

function sectionsAreObjects(frontmatter: string): boolean {
  const scalars = new Set<string>();
  for (const line of frontmatter.split(/\r?\n/)) {
    const m = /^([A-Za-z0-9_-]+):\s*(.+)$/.exec(line);
    if (m) scalars.add(m[1]);
  }
  for (const line of frontmatter.split(/\r?\n/)) {
    if (/^[ \t]/.test(line)) {
      // the active section must not be in the scalar set — approximate check
    }
  }
  return true;
}

Try / catch

try {
  parseSandboxContract(content);
} catch (err) {
  if ((err as Error).message.includes('Invalid sandbox.md frontmatter section')) {
    // the message names the section; remove the scalar assignment for that key
  }
  throw err;
}

Prevention

When it happens

Trigger: Frontmatter like 'evaluator: something' followed by an indented ' command: x' — the section 'evaluator' is a string, not an object; or a section previously parsed as an array, so the (section as Record) cast guard fails.

Common situations: Writing 'evaluator: { ... }' inline then also adding nested keys; duplicating a key where the first occurrence set a scalar and a later indented key tries to nest under it.

Related errors


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