JuliusBrussee/caveman · error

cave_memory_ttl_invalid

cave_memory_ttl_invalid

Error message

cave_memory_ttl_invalid

What it means

memoryTTLMilliseconds parses a human TTL string (e.g. "30m", "12h", "7d") into milliseconds. This first throw fires when the string does not match the required pattern `^[1-9][0-9]*(m|h|d)$` — i.e. it is malformed, has no unit, uses an unsupported unit (s/w/y), starts with 0, is negative, or has separators/whitespace.

Solutions

  1. Format the TTL as an integer (no leading zeros) followed by `m`, `h`, or `d`, e.g. "30m", "24h", "14d".
  2. Convert unsupported units before calling: seconds→minutes ("90s"→"2m"), weeks→days ("2w"→"14d").
  3. Validate the string with the same regex client-side before passing it in.
  4. Trim whitespace and strip surrounding quotes from config/env-derived values.

Example fix

// before
memoryTTLMilliseconds(process.env.MEM_TTL ?? "30s");
// after
const ttl = (process.env.MEM_TTL ?? "30m").trim();
if (!/^[1-9][0-9]*(m|h|d)$/.test(ttl)) throw new Error("bad TTL");
memoryTTLMilliseconds(ttl);
Defensive patterns

Strategy: validation

Validate before calling

const TTL_RE = /^[1-9][0-9]*(m|h|d)$/;
if (typeof ttl !== "string" || !TTL_RE.test(ttl.trim())) {
  throw new Error(`TTL must match Nm|Nh|Nd, got: ${JSON.stringify(ttl)}`);
}

Try / catch

try {
  const ms = memoryTTLMilliseconds(ttl);
} catch (e) {
  if (e instanceof Error && e.message === "cave_memory_ttl_invalid") {
    console.error(`TTL '${ttl}' is not <integer><m|h|d> (no leading zeros, no s/w units)`);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling `memoryTTLMilliseconds("7 days")`, `memoryTTLMilliseconds("30s")`, `memoryTTLMilliseconds("0d")`, `memoryTTLMilliseconds("007h")`, `memoryTTLMilliseconds("12")` (missing unit), or passing a number/undefined instead of a string.

Common situations: Reading TTL from env/config with units like "s" or "w" that the grammar rejects; localized or spelled-out durations ("1 day"); empty string from an unset config value; copy-pasted values with whitespace or trailing punctuation.

Understand the failure class

Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/09a6292c89c56539. Report an issue: GitHub.

Appendix: source

Thrown at packages/agent/src/primitives.ts:251

  if (definition.strategy === "verbatim") {
    return definition.recovery === "exact_ccr" ? "exact_ccr" : "inline";
  }
  if (definition.strategy === "json-index") return "compress";
  return "page";
}

export interface MemoryDefinition {
  readonly kind: "memory";
  readonly namespace: string;
  readonly provenance: "local" | "project" | "external";
  readonly ttl: string;
  readonly recallBudget: number;
  readonly consent: "local_only" | "project_shared";
}

export function memoryTTLMilliseconds(value: string): number {
  const match = /^([1-9][0-9]*)(m|h|d)$/.exec(value);
  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)}`);

View on GitHub (pinned to 3ee70a1026)