{"record":{"id":"95d7d3fc28ebb15f","repo":"Yeachan-Heo/oh-my-codex","slug":"autoresearch-candidate-artifact-candidate-commit-m","errorCode":null,"errorMessage":"autoresearch candidate artifact candidate_commit must be string|null","messagePattern":"autoresearch candidate artifact candidate_commit must be string\\|null","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/autoresearch/runtime.ts","lineNumber":1036,"sourceCode":"}\n\nexport function parseAutoresearchCandidateArtifact(raw: string): AutoresearchCandidateArtifact {\n  let parsed: unknown;\n  try {\n    parsed = JSON.parse(raw);\n  } catch {\n    throw new Error('autoresearch candidate artifact must be valid JSON');\n  }\n  if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n    throw new Error('autoresearch candidate artifact must be a JSON object');\n  }\n  const record = parsed as Record<string, unknown>;\n  const status = record.status;\n  if (status !== 'candidate' && status !== 'noop' && status !== 'abort' && status !== 'interrupted') {\n    throw new Error('autoresearch candidate artifact status must be candidate|noop|abort|interrupted');\n  }\n  if (record.candidate_commit !== null && typeof record.candidate_commit !== 'string') {\n    throw new Error('autoresearch candidate artifact candidate_commit must be string|null');\n  }\n  if (typeof record.base_commit !== 'string' || !record.base_commit.trim()) {\n    throw new Error('autoresearch candidate artifact base_commit is required');\n  }\n  if (typeof record.description !== 'string') {\n    throw new Error('autoresearch candidate artifact description is required');\n  }\n  if (!Array.isArray(record.notes) || record.notes.some((note) => typeof note !== 'string')) {\n    throw new Error('autoresearch candidate artifact notes must be a string array');\n  }\n  if (typeof record.created_at !== 'string' || !record.created_at.trim()) {\n    throw new Error('autoresearch candidate artifact created_at is required');\n  }\n  return {\n    status,\n    candidate_commit: record.candidate_commit,\n    base_commit: record.base_commit,\n    description: record.description,","sourceCodeStart":1018,"sourceCodeEnd":1054,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/autoresearch/runtime.ts#L1018-L1054","documentation":"The optional candidate_commit field must be either null or a string. Numbers, booleans, objects, or arrays are rejected — candidate_commit represents the candidate git SHA and is null for noop/abort statuses.","triggerScenarios":"A worker emitting candidate_commit as a non-string (e.g. a number, or an object like {sha: '...'}), or an empty/undefined placeholder serialized as something other than null.","commonSituations":"Models wrapping the commit in an object, templates using a numeric placeholder (0) for 'no commit yet', or serialization libraries dropping null into undefined-based defaults.","solutions":["Emit candidate_commit as the commit SHA string, or literal null when there is no candidate commit","Do not wrap the SHA in an object; flatten it to a plain string","Add a template example showing candidate_commit: null for noop/abort statuses"],"exampleFix":"// before\n{\"status\":\"noop\",\"candidate_commit\":0,\"base_commit\":\"abc\",\"description\":\"...\",\"notes\":[]}\n// after\n{\"status\":\"noop\",\"candidate_commit\":null,\"base_commit\":\"abc\",\"description\":\"...\",\"notes\":[]}","handlingStrategy":"type-guard","validationCode":"const candidateCommit = parsed.candidate_commit ?? null;\nif (candidateCommit !== null && typeof candidateCommit !== 'string') {\n  throw new Error('candidate_commit must be a commit SHA string or null');\n}","typeGuard":"function isCommitOrNull(v: unknown): v is string | null {\n  return v === null || typeof v === 'string';\n}","tryCatchPattern":"try { const a = parseAutoresearchCandidateArtifact(raw); }\ncatch (e) { if (e instanceof Error && e.message.includes('candidate_commit must be string|null')) { /* flatten the SHA to a plain string or null and retry */ } throw e; }","preventionTips":["Emit candidate_commit as a bare SHA string or literal null","Show candidate_commit: null for noop/abort in template examples","Validate field types in the worker harness before persisting"],"tags":["autoresearch","type-validation","artifact","git-commit"],"backgroundTag":"json-schema-validation-failed","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}