nexu-io/open-design · error · Error

invalid memory id

Error message

invalid memory id

What it means

A memory id failed validation in entryPath(). The id must be a string matching /^[a-z0-9_]+$/, and must not exceed 96 characters. This is a defence-in-depth check because ids arrive from network requests and are used directly in filesystem path construction (path.join with the id + '.md').

Source

Thrown at apps/daemon/src/memory.ts:153

    .slice(0, 48);
  if (cleaned.length > 0) return `${safeType}_${cleaned}`;
  // FNV-1a 32-bit on the original name. Tiny, deterministic, no
  // dependencies. Collisions are still possible, but for the dozens of
  // memories a user is likely to accumulate, the birthday risk is
  // negligible.
  let h = 0x811c9dc5 >>> 0;
  for (let i = 0; i < raw.length; i++) {
    h = (h ^ raw.charCodeAt(i)) >>> 0;
    h = Math.imul(h, 0x01000193) >>> 0;
  }
  return `${safeType}_n${h.toString(36)}`;
}

function entryPath(dataDir, id) {
  // Defence in depth: the id arrives from the network. Reject anything
  // that could escape the memory dir or break the .md convention.
  if (typeof id !== 'string' || !/^[a-z0-9_]+$/.test(id) || id.length > 96) {
    throw new Error('invalid memory id');
  }
  return path.join(memoryDir(dataDir), `${id}.md`);
}

function indexPath(dataDir) {
  return path.join(memoryDir(dataDir), INDEX_FILE);
}

function configPath(dataDir) {
  return path.join(memoryDir(dataDir), CONFIG_FILE);
}

// Whitelist of fields the extraction override may contain. Anything else
// in the patch is dropped to keep `.config.json` from accumulating
// arbitrary user-supplied keys (e.g. a typo'd field that quietly breaks
// the extractor on the next restart).
const VALID_EXTRACTION_PROVIDERS = new Set([
  'anthropic',

View on GitHub (pinned to 5be4028344)

Solutions

  1. Use only lowercase alphanumeric and underscore characters in memory ids
  2. Keep ids at or under 96 characters
  3. Use deriveMemoryId(type, name) to generate safe ids automatically from type and name
  4. Sanitize external ids by lowercasing and replacing non-alphanumeric characters with underscores before passing to memory APIs

Example fix

// before — UUID with hyphens fails validation
updateMemoryTreeNode(dataDir, 'a1b2c3d4-e5f6-7890', patch);

// after — sanitize to valid slug
const safeId = 'a1b2c3d4-e5f6-7890'.toLowerCase().replace(/[^a-z0-9]+/g, '_');
updateMemoryTreeNode(dataDir, safeId, patch);
Defensive patterns

Strategy: validation

Validate before calling

const MEMORY_ID_RE = /^[a-z0-9_]+$/;
const MEMORY_ID_MAX_LEN = 96;

function assertValidMemoryId(id) {
  if (typeof id !== 'string' || !MEMORY_ID_RE.test(id) || id.length > MEMORY_ID_MAX_LEN) {
    throw new Error(`Invalid memory id: ${JSON.stringify(id)}. Must match ${MEMORY_ID_RE} and be <= ${MEMORY_ID_MAX_LEN} chars.`);
  }
}

Type guard

function isValidMemoryId(id: unknown): id is string {
  return typeof id === 'string' && /^[a-z0-9_]+$/.test(id) && id.length <= 96;
}

Prevention

When it happens

Trigger: API caller sends an id with uppercase letters, hyphens, dots, slashes, spaces, or special characters; id exceeds 96 chars; id is null, undefined, or not a string; path traversal attempt with '../' sequences.

Common situations: External system generates UUIDs with hyphens (e.g. 'a1b2c3d4-e5f6'); user-supplied id with invalid characters; camelCase id like 'myMemory'; malicious path traversal attempt.

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/f00481667a98324f. Report an issue: GitHub.