JuliusBrussee/caveman · error
cave_memory_value_invalid
cave_memory_value_invalid
Error message
cave_memory_value_invalid
What it means
The `cave_memory_remember` tool throws `cave_memory_value_invalid` when the `text` to remember is empty after trimming or longer than 8,192 characters. The local memory store stores only bounded single facts, so out-of-range values are rejected inside the tool's `execute` and surface as a tool-call error.
Solutions
- Trim the text and ensure it is 1–8,192 characters before calling; store one concise fact per call.
- Split long content into multiple smaller `remember` calls or store it via your own file tool and remember a pointer/summary instead.
- If a wrapper invokes the tool, pre-validate length and skip the call for blank text.
Example fix
// before
await memory.cave_memory_remember.execute(id, { text: longDocument }); // > 8192 chars
// after
const summary = summarize(longDocument).slice(0, 8192);
if (summary.trim()) await memory.cave_memory_remember.execute(id, { text: summary }); Defensive patterns
Strategy: validation
Validate before calling
function canRemember(text: unknown): text is string {
const t = typeof text === "string" ? text.trim() : "";
return t.length > 0 && t.length <= 8_192;
}
if (!canRemember(args.text)) throw new Error("memory text must be 1-8192 chars"); Type guard
const isMemoryText = (v: unknown): v is string => typeof v === "string" && v.trim().length > 0 && v.trim().length <= 8_192;
Try / catch
try {
await memory.cave_memory_remember.execute(id, { text });
} catch (e) {
if ((e as Error).message === "cave_memory_value_invalid") {
return { remembered: false, reason: "text empty or over 8192 chars" };
}
throw e;
} Prevention
- Store one concise fact per call; never pass whole documents.
- Truncate/split long text before calling remember.
- Skip the call entirely when the trimmed text is empty.
When it happens
Trigger: Model calling `cave_memory_remember` with `{ text: "" }`, whitespace-only text, or a text blob over 8,192 characters.
Common situations: A model pasting a whole document as a 'fact'; an empty argument from a hallucinated tool call; a caller script forwarding an unset variable as the memory text.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- cave_memory_ttl_invalid
- caveman agent: error-rate guardrail max must be in [0,1]
- caveman agent: invalid memory namespace
- caveman agent: memory recallBudget must be a non-negative…
- caveman agent: memory ttl must use positive m, h, or d…
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/395332f111d5e0c3.
Report an issue: GitHub.
Appendix: source
Thrown at packages/agent/src/runtime.ts:3166
if (used + item.entry.text.length > maxChars) continue;
hits.push(item.entry.text);
used += item.entry.text.length;
}
return {
content: [{ type: "text", text: JSON.stringify({ hits, basis: "inferred", namespace: definition.namespace }) }],
details: { namespace: definition.namespace, recallTokensEstimated: Math.ceil(used / 4) },
};
},
};
const remember: AgentTool<TSchema> = {
name: "cave_memory_remember",
label: "cave_memory_remember",
description: "Remember one explicit fact in declared local namespace.",
parameters: Type.Object({ text: Type.String() }),
executionMode: "sequential",
async execute(_toolCallId, params) {
const text = (params as { text: string }).text.trim();
if (text.length === 0 || text.length > 8_192) throw new Error("cave_memory_value_invalid");
await mutateMemories(filePath, (entries) => {
const next: MemoryEntry[] = entries.some((entry) => entry.text === text)
? entries
: [...entries, { text, createdAt: Date.now() }];
return next.length > 1_000 ? next.slice(next.length - 1_000) : next;
});
return {
content: [{ type: "text", text: JSON.stringify({ remembered: true, basis: "inferred" }) }],
details: { namespace: definition.namespace },
};
},
};
return [recall, remember];
}
function tokenize(value: string): string[] {
return value.toLowerCase().match(/[a-z0-9]{2,}/g) ?? [];
}View on GitHub (pinned to 3ee70a1026)