{"record":{"id":"915bfbd0b91960d9","repo":"JuliusBrussee/caveman","slug":"eval-evidence-line-index-1-is-not-valid-json","errorCode":null,"errorMessage":"eval evidence line ${index + 1} is not valid JSON","messagePattern":"eval evidence line (.+?) is not valid JSON","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/index.ts","lineNumber":17155,"sourceCode":"\n// auditEvalImport turns newline-delimited, source-neutral eval records into one\n// bounded batch. Server stamps tenant scope, observed basis, and external-only\n// 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    },","sourceCodeStart":17137,"sourceCodeEnd":17173,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/5184b3d11ac6a1acb7d44b9bfaa31698157cff97/packages/cli/src/index.ts#L17137-L17173","documentation":"Thrown while parsing the eval-import JSONL: every non-empty line must be a complete, valid JSON document. Line numbers are 1-based over the raw file (blank lines are skipped), so the message pinpoints the exact offending line. Parsing happens client-side before the batch POST.","triggerScenarios":"A truncated final line from an interrupted write; a pretty-printed object spanning multiple lines; stray commas or BOM characters; artifacts cut mid-record by head/tail; corrupted strings from line-ending conversions.","commonSituations":"Manually edited evidence files; concatenating outputs mid-record; producers using JSON.stringify with indentation instead of one compact object per line; files transferred through editors that re-encode them.","solutions":["Open the file at the reported line and fix or delete the malformed record","Re-emit the file programmatically: exactly one JSON.stringify(record) per line","Validate locally first: `jq -c . file.jsonl > /dev/null` reports the first bad line","If only the last line is truncated, regenerate the export"],"exampleFix":"// before (pretty-printed object inside JSONL)\n{\n  \"suite\": \"eval\"\n}\n// after\n{\"suite\":\"eval\"}","handlingStrategy":"validation","validationCode":"// Validate every line before handing the file to the CLI.\nconst bad: number[] = [];\nfor (const [i, line] of (await readFile(file, 'utf8')).split(/\\r?\\n/).entries()) {\n  const t = line.trim();\n  if (!t) continue;\n  try { JSON.parse(t); } catch { bad.push(i + 1); }\n}\nif (bad.length) throw new Error(`invalid JSON on lines: ${bad.join(',')}`);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Generate JSONL only via JSON.stringify per record — never pretty-print","Verify exports with jq before importing","Write files atomically (temp file + rename) to avoid truncated tails"],"tags":["jsonl","parsing","eval","import"],"backgroundTag":"jsonl-parse-error","analyzedSha":"5184b3d11ac6a1acb7d44b9bfaa31698157cff97","analyzedAt":"2026-08-18T03:14:35.516Z","contentChangedAt":"2026-08-18T03:14:35.516Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}