Yeachan-Heo/oh-my-codex · error · Error
autoresearch candidate artifact created_at is required
Error message
autoresearch candidate artifact created_at is required
What it means
The candidate artifact validator requires a 'created_at' timestamp as a non-empty string. This error fires when created_at is absent, not a string, or a whitespace-only string. It guarantees every candidate artifact carries a creation timestamp for ordering and audit.
Source
Thrown at src/autoresearch/runtime.ts:1048
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');
}
if (typeof record.created_at !== 'string' || !record.created_at.trim()) {
throw new Error('autoresearch candidate artifact created_at is required');
}
return {
status,
candidate_commit: record.candidate_commit,
base_commit: record.base_commit,
description: record.description,
notes: record.notes,
created_at: record.created_at,
};
}
async function readCandidateArtifact(candidateFile: string): Promise<AutoresearchCandidateArtifact> {
if (!existsSync(candidateFile)) {
throw new Error(`autoresearch_candidate_missing:${candidateFile}`);
}
return parseAutoresearchCandidateArtifact(await readFile(candidateFile, 'utf-8'));
}
View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Open the candidate artifact and add created_at as an ISO 8601 string, e.g. new Date().toISOString()
- Fix the producer to always set created_at before writing the file
- If the file is truncated from an interrupted run, delete it and re-run the autoresearch session instead of patching
Example fix
// before
{"status":"candidate","created_at":1735689600000}
// after
{"status":"candidate","created_at":"2025-01-01T00:00:00.000Z"} Defensive patterns
Strategy: validation
Validate before calling
const raw = JSON.parse(text);
if (typeof raw.created_at !== 'string' || !raw.created_at.trim()) {
raw.created_at = new Date().toISOString(); // or reject upstream
} Type guard
function hasCreatedAt(v: unknown): v is { created_at: string } {
return typeof v === 'object' && v !== null && typeof (v as any).created_at === 'string' && (v as any).created_at.trim() !== '';
} Prevention
- Serialize timestamps with toISOString() at write time
- Treat missing created_at as a corrupt artifact and re-run the session
When it happens
Trigger: parseAutoresearchCandidateArtifact on JSON where 'created_at' is missing, null, a number (epoch), or an empty/whitespace string.
Common situations: Generators writing epoch numbers instead of ISO strings, hand-authored artifacts omitting the field, or a truncated/interrupted run that wrote an incomplete file.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- autoresearch candidate artifact notes must be a string array
- Invalid autoresearch-goal mission at ${repoRelative(cwd, pat
- Autoresearch goal ${mission.slug} cannot complete until prof
- autoresearch candidate artifact must be valid JSON
- autoresearch candidate artifact must be a JSON object
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/ed6e2dced13c677d.
Report an issue: GitHub.