{"record":{"id":"6958ea369b9b62fc","repo":"nexu-io/open-design","slug":"failed-to-read-memory-entry-after-write","errorCode":null,"errorMessage":"failed to read memory entry after write","messagePattern":"failed to read memory entry after write","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/daemon/src/memory.ts","lineNumber":522,"sourceCode":"  });\n}\n\nexport async function upsertMemoryEntry(dataDir, input, options) {\n  const { name, description, type, body } = input || {};\n  if (!name || !isValidType(type)) {\n    throw new Error('memory entry requires `name` and a valid `type`');\n  }\n  const id = input?.id && /^[a-z0-9_]+$/.test(input.id)\n    ? input.id\n    : deriveMemoryId(type, name);\n  await ensureDir(memoryDir(dataDir));\n  await fsp.writeFile(\n    entryPath(dataDir, id),\n    renderEntryFile(name, description, type, body, options?.source ?? 'manual'),\n  );\n  await ensureIndexHasEntry(dataDir, id, name, description);\n  const entry = await readMemoryEntry(dataDir, id);\n  if (!entry) throw new Error('failed to read memory entry after write');\n  if (!options?.silent) {\n    emitChange({\n      kind: 'upsert',\n      id: entry.id,\n      name: entry.name,\n      description: entry.description,\n      type: entry.type,\n      source: options?.source ?? 'manual',\n    });\n  }\n  return entry;\n}\n\nexport async function deleteMemoryEntry(dataDir, id) {\n  try {\n    await fsp.unlink(entryPath(dataDir, id));\n  } catch {\n    // Already gone — fine. Caller doesn't care.","sourceCodeStart":504,"sourceCodeEnd":540,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/memory.ts#L504-L540","documentation":"After upsertMemoryEntry successfully wrote the .md file and updated the index, readMemoryEntry returned null when reading the entry back. This indicates the just-written file could not be found or parsed on immediate re-read, which should not happen under normal conditions.","triggerScenarios":"Filesystem permissions changed between write and read; disk full caused a partial write; antivirus/security software locked or quarantined the file; a concurrent process deleted the entry immediately after the write; the id failed entryPath validation on readback (unlikely since it was validated for write).","commonSituations":"Filesystem permissions issue on the data directory; disk full mid-operation; concurrent memory deletion; OS-level file locking (Windows antivirus, macOS Time Machine snapshot); NFS or network filesystem consistency delay.","solutions":["Check filesystem permissions on the memory data directory and available disk space","Verify no concurrent process is modifying or deleting memory entries","Retry the upsert operation after a brief delay","Check daemon logs for filesystem-level errors during the write/read cycle"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"const MAX_WRITE_RETRIES = 2;\nfor (let attempt = 0; attempt <= MAX_WRITE_RETRIES; attempt++) {\n  try {\n    return await upsertMemoryEntry(dataDir, input, options);\n  } catch (err) {\n    if (err.message.includes('failed to read memory entry after write') && attempt < MAX_WRITE_RETRIES) {\n      await sleep(200 * (attempt + 1));\n      continue;\n    }\n    throw err;\n  }\n}","preventionTips":["Ensure the daemon data directory has stable read/write permissions and adequate disk space","Avoid concurrent memory deletion while upsert operations are in flight","Monitor for filesystem-level errors (disk full, permission changes, antivirus interference) in daemon logs","On networked filesystems (NFS, SMB), be aware of consistency delays that can cause immediate readback to fail"],"tags":["memory","filesystem","write-failure","race-condition"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}