{"record":{"id":"67efc2220f7b2134","repo":"JuliusBrussee/caveman","slug":"eval-evidence-line-index-1-must-be-a-json-obj","errorCode":null,"errorMessage":"eval evidence line ${index + 1} must be a JSON object","messagePattern":"eval evidence line (.+?) must be a JSON object","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/index.ts","lineNumber":17158,"sourceCode":"// authority; CI cannot promote its own results into rollout authority.\nasync function auditEvalImport(argv: string[]) {\n  const file = positionalAfterOptions(argv.slice(1), new Set([\"--project\"]));\n  if (!file) throw new Error(`usage: ${invokedCommand(\"audit\")} eval-import <evidence.jsonl> [--project <uuid>] [--dry-run]`);\n  const data = await readFile(file);\n  if (data.byteLength > 4 * 1024 * 1024) throw new Error(\"eval evidence file exceeds 4 MiB batch limit\");\n\n  const items: Record<string, unknown>[] = [];\n  for (const [index, rawLine] of data.toString(\"utf8\").split(/\\r?\\n/).entries()) {\n    const line = rawLine.trim();\n    if (!line) continue;\n    let parsed: unknown;\n    try {\n      parsed = JSON.parse(line);\n    } catch {\n      throw new Error(`eval evidence line ${index + 1} is not valid JSON`);\n    }\n    if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n      throw new Error(`eval evidence line ${index + 1} must be a JSON object`);\n    }\n    items.push(parsed as Record<string, unknown>);\n    if (items.length > 1000) throw new Error(\"eval evidence batch exceeds 1000 records\");\n  }\n  if (items.length === 0) throw new Error(\"eval evidence file contains no records\");\n\n  const cfg = await config();\n  const project = flagFrom(argv, \"--project\", cfg.projectId ?? \"\");\n  const response = await fetch(`${cfg.baseURL}/api/v1/eval-evidence/batches`, {\n    method: \"POST\",\n    headers: {\n      authorization: `Bearer ${cfg.token}`,\n      \"content-type\": \"application/json\",\n      \"x-cave-csrf\": \"cli\",\n    },\n    body: JSON.stringify({\n      ...(project ? { project_id: project } : {}),\n      dry_run: argv.includes(\"--dry-run\"),","sourceCodeStart":17140,"sourceCodeEnd":17176,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/5184b3d11ac6a1acb7d44b9bfaa31698157cff97/packages/cli/src/index.ts#L17140-L17176","documentation":"Shape guard for eval-import records: each JSONL line must parse to a JSON object at the top level. Arrays, strings, numbers, booleans, and null are rejected even though they are valid JSON, because the batch endpoint consumes only object-shaped records.","triggerScenarios":"A line holding a bare array (e.g. a JSON-array export stripped of brackets but leaving array tokens), a quoted string line, a bare number/boolean, or a null serialized by sparse pipelines.","commonSituations":"Converting a JSON array export to JSONL incorrectly; logging frameworks emitting string lines into the same file; empty rows serialized as null.","solutions":["Fix the reported line by wrapping the value in an object or dropping it","Regenerate the export as exactly one object per line","Validate shape locally: `jq -c 'select(type != \"object\")' file.jsonl` lists every non-object line"],"exampleFix":"// before\n[\"suite-a\", \"suite-b\"]\n// after\n{\"suite\":\"suite-a\"}\n{\"suite\":\"suite-b\"}","handlingStrategy":"type-guard","validationCode":"const allObjects = lines\n  .filter((l) => l.trim())\n  .every((l) => {\n    const v = JSON.parse(l);\n    return v !== null && typeof v === 'object' && !Array.isArray(v);\n  });\nif (!allObjects) throw new Error('evidence contains non-object lines — expected one JSON object per line');","typeGuard":"const isRecord = (v: unknown): v is Record<string, unknown> =>\n  typeof v === 'object' && v !== null && !Array.isArray(v);","tryCatchPattern":null,"preventionTips":["Emit only objects per line when writing JSONL","Run a jq type check in CI before import","Reject array-style exports at the producer, not at import time"],"tags":["jsonl","schema-validation","eval","import"],"backgroundTag":"jsonl-schema-validation","analyzedSha":"5184b3d11ac6a1acb7d44b9bfaa31698157cff97","analyzedAt":"2026-08-18T03:14:35.516Z","contentChangedAt":"2026-08-18T03:14:35.516Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}