Yeachan-Heo/oh-my-codex · error · Error
autoresearch candidate artifact must be a JSON object
Error message
autoresearch candidate artifact must be a JSON object
What it means
After successful JSON parsing, parseAutoresearchCandidateArtifact requires the top-level value to be a non-null, non-array object. Arrays, strings, numbers, booleans, or null are rejected before field checks run.
Source
Thrown at src/autoresearch/runtime.ts:1028
latestEvaluatorFile: manifest.latest_evaluator_file,
resultsFile: manifest.results_file,
stateFile: activeRunStateFile(projectRoot),
candidateFile: manifest.candidate_file,
repoRoot: manifest.repo_root,
worktreePath: manifest.worktree_path,
taskDescription: `autoresearch resume ${runId}`,
};
}
export function parseAutoresearchCandidateArtifact(raw: string): AutoresearchCandidateArtifact {
let parsed: unknown;
try {
parsed = JSON.parse(raw);
} catch {
throw new Error('autoresearch candidate artifact must be valid JSON');
}
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
throw new Error('autoresearch candidate artifact must be a JSON object');
}
const record = parsed as Record<string, unknown>;
const status = record.status;
if (status !== 'candidate' && status !== 'noop' && status !== 'abort' && status !== 'interrupted') {
throw new Error('autoresearch candidate artifact status must be candidate|noop|abort|interrupted');
}
if (record.candidate_commit !== null && typeof record.candidate_commit !== 'string') {
throw new Error('autoresearch candidate artifact candidate_commit must be string|null');
}
if (typeof record.base_commit !== 'string' || !record.base_commit.trim()) {
throw new Error('autoresearch candidate artifact base_commit is required');
}
if (typeof record.description !== 'string') {
throw new Error('autoresearch candidate artifact description is required');
}
if (!Array.isArray(record.notes) || record.notes.some((note) => typeof note !== 'string')) {
throw new Error('autoresearch candidate artifact notes must be a string array');
}View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Ensure the worker writes a single JSON object ({...}) as the artifact root
- If double-serialized (artifact is a JSON string containing JSON), parse once more before handing it over
- If the worker emits an array, wrap it in an object (e.g. { results: [...] }) to satisfy the contract
- Add a pre-check with JSON.parse + typeof === 'object' in your harness to fail fast with better context
Example fix
// before
const artifact = parseAutoresearchCandidateArtifact('"{\\\"status\\\":\\\"candidate\\\"}"'); // parses to a string
// after
const artifact = parseAutoresearchCandidateArtifact('{"status":"candidate",...}'); Defensive patterns
Strategy: type-guard
Validate before calling
const parsed = parseJsonSafe(raw);
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
throw new Error('Candidate artifact root must be a JSON object.');
} Type guard
function isJsonObject(v: unknown): v is Record<string, unknown> {
return typeof v === 'object' && v !== null && !Array.isArray(v);
} Try / catch
try { const a = parseAutoresearchCandidateArtifact(raw); }
catch (e) { if (e instanceof Error && e.message === 'autoresearch candidate artifact must be a JSON object') { /* fix double serialization or array wrapping in worker output */ } throw e; } Prevention
- Give workers a concrete example artifact object to mimic
- Avoid double JSON.stringify when serializing worker output
- Check the root is an object in the harness before writing the artifact
When it happens
Trigger: Passing a JSON artifact that parses to a primitive or array — e.g. a worker emitting a bare string, a JSON array of notes, or 'null' as the whole document.
Common situations: Workers wrapping the artifact in an array, emitting a quoted JSON string of the real object (double serialization), or defaulting to null/empty output on failure paths.
Related errors
- autoresearch candidate artifact must be valid JSON
- autoresearch candidate artifact notes must be a string array
- Invalid autoresearch-goal mission at ${repoRelative(cwd, pat
- autoresearch candidate artifact status must be candidate|noo
- autoresearch candidate artifact candidate_commit must be str
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/6a5c4a19bcc0ecd8.
Report an issue: GitHub.