{"record":{"id":"8b2818a3af567ae0","repo":"JuliusBrussee/caveman","slug":"local-learn-snapshot-is-unreadable-at-snapshotpa","errorCode":null,"errorMessage":"local learn snapshot is unreadable at ${snapshotPath}","messagePattern":"local learn snapshot is unreadable at (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/index.ts","lineNumber":10058,"sourceCode":"  const subject = `synced ${out.spans}${local ? \" local\" : \"\"} spans`;\n  if (out.headlineCompressionRefused) {\n    return `${subject} · compression headline refused: cache writes ${out.cacheCreationInputTokens} > cache reads ${out.cachedInputTokens} (inferred; no savings headline)${destination}`;\n  }\n  return `${subject} · ${out.tokensSaved} estimated tokens saved (inferred; counter basis ${out.tokenCountBasis})${destination}`;\n}\n\n// syncLocalPracticeFindings moves only stable ids + non-negative token rates\n// from the current learn snapshot. Titles, suggestions, evidence, file paths,\n// and payload text never leave the machine. Empty snapshots are sent so stale\n// rows for this user are removed server-side.\nasync function syncLocalPracticeFindings(cfg: Config): Promise<PracticeSyncOutcome> {\n  const snapshotPath = join(cavemanHome(), \"reports\", \"caveman-learn.json\");\n  let raw: Record<string, unknown>;\n  try {\n    raw = JSON.parse(readFileSync(snapshotPath, \"utf8\")) as Record<string, unknown>;\n  } catch (error) {\n    if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return { kind: \"no_snapshot\" };\n    throw new Error(`local learn snapshot is unreadable at ${snapshotPath}`);\n  }\n\n  if (!Array.isArray(raw.sinks)) {\n    throw new Error(`local learn snapshot has no sinks array at ${snapshotPath}`);\n  }\n  const observed = typeof raw.generated_at === \"string\" ? new Date(raw.generated_at) : null;\n  if (!observed || Number.isNaN(observed.valueOf())) {\n    throw new Error(`local learn snapshot has no valid generated_at at ${snapshotPath}`);\n  }\n  const sessions = typeof raw.sessions_scanned === \"number\" && Number.isFinite(raw.sessions_scanned)\n    ? Math.max(0, Math.trunc(raw.sessions_scanned))\n    : 0;\n  const counter = (value: unknown) =>\n    typeof value === \"number\" && Number.isFinite(value) ? Math.max(0, Math.trunc(value)) : 0;\n\n  const findings = raw.sinks\n    .filter((sink): sink is Record<string, unknown> =>\n      !!sink && typeof sink === \"object\" && !Array.isArray(sink))","sourceCodeStart":10040,"sourceCodeEnd":10076,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/5184b3d11ac6a1acb7d44b9bfaa31698157cff97/packages/cli/src/index.ts#L10040-L10076","documentation":"syncLocalPracticeFindings cannot read the local learn snapshot file at ~/.caveman/reports/caveman-learn.json (it exists but is unreadable/invalid JSON). Only a missing file (ENOENT) is treated as 'no snapshot'; other read failures surface this error.","triggerScenarios":"Thrown at packages/cli/src/index.ts:9213 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Regenerate the snapshot by running `caveman learn`","Check file permissions on the path; delete a corrupt snapshot and re-learn"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"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"}