JuliusBrussee/caveman · error · Error
local learn snapshot has no valid generated_at at ${snapshot
Error message
local learn snapshot has no valid generated_at at ${snapshotPath} What it means
The learn snapshot at ~/.caveman/reports/caveman-learn.json parsed as JSON but its generated_at field is missing or not a valid timestamp. Without a trustworthy generation time the snapshot cannot be freshness-checked, so syncing local practice findings is refused rather than sending data of unknown age.
Source
Thrown at packages/cli/src/index.ts:10066
// from the current learn snapshot. Titles, suggestions, evidence, file paths,
// and payload text never leave the machine. Empty snapshots are sent so stale
// rows for this user are removed server-side.
async function syncLocalPracticeFindings(cfg: Config): Promise<PracticeSyncOutcome> {
const snapshotPath = join(cavemanHome(), "reports", "caveman-learn.json");
let raw: Record<string, unknown>;
try {
raw = JSON.parse(readFileSync(snapshotPath, "utf8")) as Record<string, unknown>;
} catch (error) {
if ((error as NodeJS.ErrnoException).code === "ENOENT") return { kind: "no_snapshot" };
throw new Error(`local learn snapshot is unreadable at ${snapshotPath}`);
}
if (!Array.isArray(raw.sinks)) {
throw new Error(`local learn snapshot has no sinks array at ${snapshotPath}`);
}
const observed = typeof raw.generated_at === "string" ? new Date(raw.generated_at) : null;
if (!observed || Number.isNaN(observed.valueOf())) {
throw new Error(`local learn snapshot has no valid generated_at at ${snapshotPath}`);
}
const sessions = typeof raw.sessions_scanned === "number" && Number.isFinite(raw.sessions_scanned)
? Math.max(0, Math.trunc(raw.sessions_scanned))
: 0;
const counter = (value: unknown) =>
typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.trunc(value)) : 0;
const findings = raw.sinks
.filter((sink): sink is Record<string, unknown> =>
!!sink && typeof sink === "object" && !Array.isArray(sink))
.filter((sink) => typeof sink.practice_id === "string" && sink.practice_id.length > 0)
.map((sink) => ({
sink_id: typeof sink.sink_id === "string" ? sink.sink_id : "",
practice_id: sink.practice_id as string,
basis: "inferred",
tokens_per_turn: counter(sink.tokens_per_turn),
tokens_per_day_rate: counter(sink.tokens_per_day_rate),
sessions_scanned: sessions,View on GitHub (pinned to 5184b3d11a)
Solutions
- Regenerate the snapshot via `caveman learn` so generated_at is written correctly
- Check for manual edits or partial writes to caveman-learn.json
Defensive patterns
Strategy: type-guard
When it happens
Trigger: Thrown at packages/cli/src/index.ts:9221 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of JuliusBrussee/caveman@5184b3d11a (2026-08-18).
Data as JSON: /api/errors/9ab72f5d8e3af189.
Report an issue: GitHub.