affaan-m/ECC · error · Error
Memory already exists; writes are create-only.
Error message
Memory ${memory.id} already exists; writes are create-only. What it means
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.
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.
Example fix
// before
saveMemory({ id: 'run-2026-09-16', ... }); // second run -> EEXIST
// after
saveMemory({ id: `run-2026-09-16-${crypto.randomUUID()}`, ... }); Defensive patterns
Strategy: try-catch
Validate before calling
const dest = path.join(vaultRoot, `${memory.kind}s`, `${memory.id}.md`);
if (fs.existsSync(dest)) throw new Error(`Memory ${memory.id} already exists; pick a new id or update it.`); Try / catch
try {
saveMemory(memory);
} catch (err) {
if (err.message.includes('already exists; writes are create-only')) {
// switch to update API or generate a new id
} else throw err;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- must not contain duplicate values.
- Memory is duplicated in files.
- Ambiguous duplicate bundle request
- Claude settings contains multiple hooks for event
- Duplicate memory frontmatter field in
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/20a151bc96869293.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/memory-vault.js:339
const memory = normalizeSaveInput(input || {}, options);
const secretKinds = findPotentialSecrets(JSON.stringify(memory));
if (secretKinds.length > 0) {
throw new Error(`Refusing to save memory containing a suspected secret (${secretKinds.join(', ')}).`);
}
const root = assertMemoryRootSafe(roots, memory.scope);
fs.mkdirSync(root, { recursive: true, mode: 0o700 });
ensureProjectScopeIgnored(roots, memory.scope);
const directory = path.join(root, `${memory.kind}s`);
assertMemoryDirectorySafe(directory, root);
fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
const destination = path.join(directory, `${memory.id}.md`);
try {
writeCreateOnlyTextFile(destination, serializeMemoryDocument(memory), root);
} catch (error) {
if (error && error.code === 'EEXIST') {
throw new Error(`Memory ${memory.id} already exists; writes are create-only.`);
}
throw error;
}
return { memory, path: destination };
}
function walkMemoryRoot(root, maxEntries = MAX_FILES) {
if (!root || !fs.existsSync(root)) {
return {
paths: [],
skippedSymlinks: [],
skippedSymlinkCount: 0,
truncated: false,
visitedCount: 0,
};
}
const paths = [];View on GitHub (pinned to 8321021c54)