JuliusBrussee/caveman · error
caveman agent: invalid memory namespace
Error message
caveman agent: invalid memory namespace ${JSON.stringify(options.namespace)} What it means
The `memory()` factory validates that the namespace identifier matches `^[a-z0-9][a-z0-9_-]{0,95}$` — lowercase alphanumerics, hyphens, and underscores, 1–96 chars, starting with a lowercase letter or digit. This error is thrown when the namespace string violates that rule, since namespaces key stored memories and must be a safe, portable identifier.
Solutions
- Rewrite the namespace to lowercase alphanumerics with `-`/`_` separators, 1–96 chars, e.g. "my-project" or "user_42_notes".
- Normalize programmatically before calling: `namespace.toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+/, "").slice(0, 96) || "default"`.
- Don't derive the namespace from raw directory names; use an explicit, sanitized constant per project.
- Check length: truncate long slugs to 96 characters.
Example fix
// before
memory({ namespace: projectDirName, ... });
// after
const namespace = projectDirName.toLowerCase()
.replace(/[^a-z0-9_-]+/g, "-").replace(/^-+/, "").slice(0, 96) || "default";
memory({ namespace, ... }); Defensive patterns
Strategy: validation
Validate before calling
const NS_RE = /^[a-z0-9][a-z0-9_-]{0,95}$/;
if (!NS_RE.test(namespace)) {
throw new Error(`namespace must match [a-z0-9][a-z0-9_-]{0,95}, got: ${namespace}`);
} Try / catch
try {
const mem = memory({ namespace, ttl: "30d", recallBudget: 100 });
} catch (e) {
if (e instanceof Error && e.message.startsWith("caveman agent: invalid memory namespace")) {
console.error(`namespace '${namespace}' invalid — slugify to lowercase [a-z0-9_-], max 96 chars`);
} else throw e;
} Prevention
- Slugify derived names (repo/folder/user) to lowercase kebab-case before use.
- Never pass raw directory names or interpolated variables as namespaces without sanitizing.
- Enforce a max length of 96 characters and no leading `-`/`_`.
- Define namespaces as explicit constants in project config rather than computing them at call sites.
When it happens
Trigger: Calling `memory({ namespace: "My Project" })` (uppercase/space), `namespace: ""`, `namespace: "-starts-with-dash"`, `namespace: "proj.name"` (dots not allowed), or a namespace longer than 96 characters.
Common situations: Deriving the namespace from a project folder name or git repo name (which often contain uppercase, dots, or spaces); interpolating user IDs with uppercase or special characters; template strings that yield empty namespace when a variable is undefined.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- cave_memory_ttl_invalid
- cave_memory_value_invalid
- caveman agent: invalid agent id
- 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/75c30aefd6d4ad56.
Report an issue: GitHub.
Appendix: source
Thrown at packages/agent/src/primitives.ts:269
if (!match) throw new Error("cave_memory_ttl_invalid");
const amount = Number(match[1]);
const scale = match[2] === "m" ? 60_000 : match[2] === "h" ? 3_600_000 : 86_400_000;
const milliseconds = amount * scale;
if (!Number.isSafeInteger(amount) || !Number.isSafeInteger(milliseconds) || milliseconds <= 0) {
throw new Error("cave_memory_ttl_invalid");
}
return milliseconds;
}
export function memory(options: {
namespace: string;
provenance?: MemoryDefinition["provenance"];
ttl: string;
recallBudget: number;
consent?: MemoryDefinition["consent"];
}): MemoryDefinition {
if (!/^[a-z0-9][a-z0-9_-]{0,95}$/.test(options.namespace)) {
throw new Error(`caveman agent: invalid memory namespace ${JSON.stringify(options.namespace)}`);
}
if (!Number.isSafeInteger(options.recallBudget) || options.recallBudget < 0) {
throw new Error("caveman agent: memory recallBudget must be a non-negative integer");
}
try {
memoryTTLMilliseconds(options.ttl);
} catch {
throw new Error("caveman agent: memory ttl must use positive m, h, or d duration");
}
// Fail closed at CONSTRUCTION, not at tool-call time: the durable
// store implements only local, single-tenant memory. A `project`/`external`
// provenance or a `project_shared` consent is a shared-backend contract this
// package does not provide, so it is refused here rather than burning a model
// turn to discover a config the framework already knew was unsupported.
const provenance = options.provenance ?? "local";
if (provenance !== "local") {
throw new Error("cave_memory_provenance_unsupported: only \"local\" memory is supported");
}View on GitHub (pinned to 3ee70a1026)