nexu-io/open-design · error · Error

memory not found

Error message

memory not found

What it means

readMemoryEntry returned null when updateMemoryTreeNode tried to load the current entry before patching it. The entry file (.md) does not exist at the expected path under the memory directory, so there is nothing to update.

Source

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

  const { summary, body } = summarize(id, raw, stat.mtimeMs);
  return { ...summary, body };
}

function renderEntryFile(name, description, type, body, source) {
  const safeName = String(name || 'Untitled').replace(/\r?\n/g, ' ').trim();
  const safeDesc = String(description || '').replace(/\r?\n/g, ' ').trim();
  const safeType = isValidType(type) ? type : 'user';
  const safeSource = VALID_SOURCES.has(source) ? source : 'manual';
  const trimmedBody = String(body || '').replace(/^\s+/, '');
  return `---\nname: ${safeName}\ndescription: ${safeDesc}\ntype: ${safeType}\nsource: ${safeSource}\n---\n\n${trimmedBody}\n`;
}

export async function updateMemoryTreeNode(dataDir, id, patch) {
  if (typeof id !== 'string' || id.startsWith('folder:')) {
    throw new Error('memory tree folders are derived and cannot be edited');
  }
  const current = await readMemoryEntry(dataDir, id);
  if (!current) throw new Error('memory not found');
  const nextType = isValidType(patch?.type) ? patch.type : current.type;
  return upsertMemoryEntry(dataDir, {
    id,
    name:
      typeof patch?.name === 'string' && patch.name.trim()
        ? patch.name
        : current.name,
    description:
      typeof patch?.description === 'string'
        ? patch.description
        : current.description,
    type: nextType,
    body: typeof patch?.body === 'string' ? patch.body : current.body,
  });
}

export async function upsertMemoryEntry(dataDir, input, options) {
  const { name, description, type, body } = input || {};

View on GitHub (pinned to 5be4028344)

Solutions

  1. Verify the entry id exists by listing current memory entries before attempting to update
  2. Refresh the memory list to get the current set of valid entry ids
  3. If the entry should exist, create it first via upsertMemoryEntry instead of updating
  4. Check for concurrent memory modification operations
Defensive patterns

Strategy: validation

Validate before calling

// Check entry existence before updating
import { readMemoryEntry } from './memory';

async function assertMemoryEntryExists(dataDir, id) {
  const entry = await readMemoryEntry(dataDir, id);
  if (!entry) {
    throw new Error(`Memory entry not found: ${id}. It may have been deleted. Refresh the list and try again.`);
  }
  return entry;
}

Try / catch

try {
  await updateMemoryTreeNode(dataDir, id, patch);
} catch (err) {
  if (err.message === 'memory not found') {
    // Entry was deleted — offer to create instead
    return upsertMemoryEntry(dataDir, { id, ...patch });
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling updateMemoryTreeNode with an id that was never created; the entry was deleted between the UI listing it and the update attempt; a concurrent process removed the .md file; filesystem issue prevented reading.

Common situations: Stale UI showing an entry that was deleted elsewhere; race condition between a delete and an update on the same entry; manual filesystem cleanup removed memory .md files; the id was fabricated by the caller and never corresponded to a real entry.

Related errors


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