{"record":{"id":"20a151bc96869293","repo":"affaan-m/ECC","slug":"memory-memory-id-already-exists-writes-are-cre","errorCode":null,"errorMessage":"Memory ${memory.id} already exists; writes are create-only.","messagePattern":"Memory (.+?) already exists; writes are create-only\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/memory-vault.js","lineNumber":339,"sourceCode":"  const memory = normalizeSaveInput(input || {}, options);\n  const secretKinds = findPotentialSecrets(JSON.stringify(memory));\n  if (secretKinds.length > 0) {\n    throw new Error(`Refusing to save memory containing a suspected secret (${secretKinds.join(', ')}).`);\n  }\n\n  const root = assertMemoryRootSafe(roots, memory.scope);\n  fs.mkdirSync(root, { recursive: true, mode: 0o700 });\n  ensureProjectScopeIgnored(roots, memory.scope);\n  const directory = path.join(root, `${memory.kind}s`);\n  assertMemoryDirectorySafe(directory, root);\n  fs.mkdirSync(directory, { recursive: true, mode: 0o700 });\n  const destination = path.join(directory, `${memory.id}.md`);\n\n  try {\n    writeCreateOnlyTextFile(destination, serializeMemoryDocument(memory), root);\n  } catch (error) {\n    if (error && error.code === 'EEXIST') {\n      throw new Error(`Memory ${memory.id} already exists; writes are create-only.`);\n    }\n    throw error;\n  }\n  return { memory, path: destination };\n}\n\nfunction walkMemoryRoot(root, maxEntries = MAX_FILES) {\n  if (!root || !fs.existsSync(root)) {\n    return {\n      paths: [],\n      skippedSymlinks: [],\n      skippedSymlinkCount: 0,\n      truncated: false,\n      visitedCount: 0,\n    };\n  }\n\n  const paths = [];","sourceCodeStart":321,"sourceCodeEnd":357,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/memory-vault.js#L321-L357","documentation":"Memory writes in the vault are strictly create-only: writeCreateOnlyTextFile opens the destination with exclusive-create semantics, and if the file for that memory id already exists the resulting EEXIST is converted into this explicit error. This prevents accidental overwriting or mutation of existing memories.","triggerScenarios":"Calling saveMemory with a memory whose id maps to an existing <kind>s/<id>.md file in the vault root. Any second save with the same id fails, even with identical content.","commonSituations":"Re-running an idempotent-looking script twice; two agents generating the same memory id; assuming saveMemory behaves like an upsert when it is insert-only.","solutions":["Use a new, unique memory id for the new memory.","If the intent is to update, use the library's update path (e.g. load the existing memory via lookup/read and the update API) rather than save.","Delete the existing memory file explicitly if replacement is truly intended, then save."],"exampleFix":"// before\nsaveMemory({ id: 'run-2026-09-16', ... }); // second run -> EEXIST\n// after\nsaveMemory({ id: `run-2026-09-16-${crypto.randomUUID()}`, ... });","handlingStrategy":"try-catch","validationCode":"const dest = path.join(vaultRoot, `${memory.kind}s`, `${memory.id}.md`);\nif (fs.existsSync(dest)) throw new Error(`Memory ${memory.id} already exists; pick a new id or update it.`);","typeGuard":null,"tryCatchPattern":"try {\n  saveMemory(memory);\n} catch (err) {\n  if (err.message.includes('already exists; writes are create-only')) {\n    // switch to update API or generate a new id\n  } else throw err;\n}","preventionTips":["Generate ids with timestamps/UUIDs for one-off memories.","Remember saveMemory is insert-only, never an upsert.","Check existence before saving in scripts that may re-run.","Use the update API for modifying existing memories."],"tags":["duplicate","create-only","memory-vault"],"backgroundTag":"file-already-exists","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}