Yeachan-Heo/oh-my-codex · error · Error
sandbox.md frontmatter evaluator.keep_policy must be one of:
Error message
sandbox.md frontmatter evaluator.keep_policy must be one of: score_improvement, pass_only.
What it means
parseKeepPolicy throws when evaluator.keep_policy is a non-empty string but not one of the two supported values after trimming/lowercasing: 'pass_only' or 'score_improvement'. The v1 contract only defines these two retention policies.
Source
Thrown at src/autoresearch/contracts.ts:144
}
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();
if (!normalized) return undefined;
if (normalized === 'pass_only') return 'pass_only';
if (normalized === 'score_improvement') return 'score_improvement';
throw contractError('sandbox.md frontmatter evaluator.keep_policy must be one of: score_improvement, pass_only.');
}
export function parseSandboxContract(content: string): ParsedSandboxContract {
const { frontmatter, body } = extractFrontmatter(content);
const parsedFrontmatter = parseSimpleYamlFrontmatter(frontmatter);
const evaluatorRaw = parsedFrontmatter.evaluator;
if (!evaluatorRaw || typeof evaluatorRaw !== 'object' || Array.isArray(evaluatorRaw)) {
throw contractError(EVALUATOR_BLOCK_ERROR);
}
const evaluator = evaluatorRaw as { command?: unknown; format?: unknown; keep_policy?: unknown };
const command = typeof evaluator.command === 'string'
? evaluator.command.trim()
: '';
const format = typeof evaluator.format === 'string'
? evaluator.format.trim().toLowerCase()
: '';View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Use exactly 'keep_policy: score_improvement' or 'keep_policy: pass_only' (snake_case, case-insensitive).
- Delete the key to fall back to the default behavior.
- Double-check for hyphens vs underscores and stray characters.
Example fix
# before evaluator: keep_policy: pass-only # after evaluator: keep_policy: pass_only
Defensive patterns
Strategy: validation
Validate before calling
const VALID_KEEP_POLICIES = new Set(['pass_only', 'score_improvement']);
function keepPolicyIsValid(raw: unknown): boolean {
return raw === undefined || (typeof raw === 'string' && (raw.trim() === '' || VALID_KEEP_POLICIES.has(raw.trim().toLowerCase())));
} Type guard
const isKeepPolicy = (v: unknown): v is 'pass_only' | 'score_improvement' => v === 'pass_only' || v === 'score_improvement';
Try / catch
try {
parseSandboxContract(content);
} catch (err) {
if ((err as Error).message.includes('keep_policy must be one of')) {
// correct to pass_only or score_improvement (snake_case)
}
throw err;
} Prevention
- Use only pass_only or score_improvement.
- Prefer snake_case; avoid hyphens.
- Omit the key when unsure to use the default.
When it happens
Trigger: Frontmatter with 'keep_policy: always', 'keep_policy: none', or a typo like 'pass-only' or 'passonly' — normalized string matches neither accepted constant.
Common situations: Typos in policy names; using kebab-case instead of snake_case; guessing policy names from other tools ('retain', 'keep-all').
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- sandbox.md frontmatter evaluator.keep_policy must be a strin
- ${filePath} frontmatter "${key}" must not be empty
- ${filePath} frontmatter "${key}" must be a single-line strin
- ${filePath} frontmatter "${key}" has an unterminated quoted
- ${filePath} must start with YAML frontmatter containing non-
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/6d1809b5eec94fc2.
Report an issue: GitHub.