{"record":{"id":"e7c653a180f3fae6","repo":"nexu-io/open-design","slug":"memory-tree-folders-are-derived-and-cannot-be-edit","errorCode":null,"errorMessage":"memory tree folders are derived and cannot be edited","messagePattern":"memory tree folders are derived and cannot be edited","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/daemon/src/memory.ts","lineNumber":487,"sourceCode":"  } catch {\n    return null;\n  }\n  const { summary, body } = summarize(id, raw, stat.mtimeMs);\n  return { ...summary, body };\n}\n\nfunction renderEntryFile(name, description, type, body, source) {\n  const safeName = String(name || 'Untitled').replace(/\\r?\\n/g, ' ').trim();\n  const safeDesc = String(description || '').replace(/\\r?\\n/g, ' ').trim();\n  const safeType = isValidType(type) ? type : 'user';\n  const safeSource = VALID_SOURCES.has(source) ? source : 'manual';\n  const trimmedBody = String(body || '').replace(/^\\s+/, '');\n  return `---\\nname: ${safeName}\\ndescription: ${safeDesc}\\ntype: ${safeType}\\nsource: ${safeSource}\\n---\\n\\n${trimmedBody}\\n`;\n}\n\nexport async function updateMemoryTreeNode(dataDir, id, patch) {\n  if (typeof id !== 'string' || id.startsWith('folder:')) {\n    throw new Error('memory tree folders are derived and cannot be edited');\n  }\n  const current = await readMemoryEntry(dataDir, id);\n  if (!current) throw new Error('memory not found');\n  const nextType = isValidType(patch?.type) ? patch.type : current.type;\n  return upsertMemoryEntry(dataDir, {\n    id,\n    name:\n      typeof patch?.name === 'string' && patch.name.trim()\n        ? patch.name\n        : current.name,\n    description:\n      typeof patch?.description === 'string'\n        ? patch.description\n        : current.description,\n    type: nextType,\n    body: typeof patch?.body === 'string' ? patch.body : current.body,\n  });\n}","sourceCodeStart":469,"sourceCodeEnd":505,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/memory.ts#L469-L505","documentation":"updateMemoryTreeNode was called with an id that starts with 'folder:'. Folder-prefixed ids are virtual/derived groupings in the memory tree UI — they represent categories, not editable entries. There is no .md file on disk for a folder node, so editing is rejected.","triggerScenarios":"The UI or API caller sends a PATCH/UPDATE request targeting a folder node id (e.g. 'folder:profile', 'folder:user'); the tree component doesn't distinguish between leaf entries and folder groupings when dispatching edits.","commonSituations":"Frontend tree component incorrectly allows an edit action on a folder/collapsed group node; API client copies a tree node id without checking whether it's a folder; a drag-and-drop or inline-edit handler fires on the wrong node type.","solutions":["Only call updateMemoryTreeNode for leaf entry ids (those not starting with 'folder:')","Filter out folder nodes from edit operations in the UI before dispatching","Check !id.startsWith('folder:') before calling the update API"],"exampleFix":"// before — attempting to edit a derived folder node\nupdateMemoryTreeNode(dataDir, 'folder:profile', { name: '...' });\n\n// after — guard against folder ids before calling\nif (!id.startsWith('folder:')) {\n  await updateMemoryTreeNode(dataDir, id, patch);\n}","handlingStrategy":"validation","validationCode":"function isEditableMemoryNode(id) {\n  return typeof id === 'string' && !id.startsWith('folder:');\n}\n\n// Before calling updateMemoryTreeNode:\nif (!isEditableMemoryNode(id)) {\n  throw new Error(`Cannot edit derived folder node: ${id}`);\n}","typeGuard":"function isEditableMemoryId(id: string): boolean {\n  return typeof id === 'string' && !id.startsWith('folder:');\n}","tryCatchPattern":null,"preventionTips":["In the UI tree component, disable edit actions on folder/group nodes so the update API is never called with a folder id","Check !id.startsWith('folder:') before dispatching update requests from API clients","Distinguish leaf entries from folder groupings at the data layer, not just the presentation layer"],"tags":["memory","validation","tree-structure"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}