affaan-m/ECC · error · Error
Memory is duplicated in files.
Error message
Memory ${memoryId} is duplicated in ${matches.length} files. What it means
The vault expects each memory id to resolve to exactly one file. During id lookup, if more than one loaded entry matches the same memory id (after harness filtering), the library throws this error instead of guessing which duplicate is authoritative. Duplicates typically arise from files written outside the library's create-only safeguards.
Solutions
- Locate the duplicate files (search the vault for the id in frontmatter) and delete or rename one.
- Give one copy a new unique id and re-save it properly via saveMemory.
- Reconcile merged/synced vault directories so each id exists once.
- Avoid manual edits/copies inside the vault; use library APIs.
Example fix
// before # vault contains notes/abc.md and references/abc.md with the same id: abc // after # rename the second file's memory id to abc-ref and save via the API, or delete the stale copy rm vault/references/abc.md
Defensive patterns
Strategy: try-catch
Validate before calling
const dupes = loadedEntries.filter(e => e.memory.id === memoryId);
if (dupes.length > 1) console.warn(`Memory ${memoryId} duplicated across ${dupes.map(d => d.path).join(', ')}`); Try / catch
try {
const memory = lookupMemory(memoryId);
} catch (err) {
if (err.message.includes('is duplicated')) {
// locate and remove the duplicate file, then retry the lookup
} else throw err;
} Prevention
- Never copy or manually create .md files inside the vault.
- Deduplicate vault directories before merging vaults from multiple machines.
- Periodically scan the vault for duplicate ids.
- Treat memory ids as globally unique across all kind directories.
When it happens
Trigger: Two files in the vault (possibly in different kind directories or roots) both parse to memories with the same id, and a lookup by that id matches both.
Common situations: Manually copying memory .md files in the vault; merging vault directories from two machines; a sync tool duplicating files; editing an id inside a file to match an existing one.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- must not contain duplicate values.
- Memory already exists; writes are create-only.
- Ambiguous duplicate bundle request
- apply_local produced an invalid report
- Claude settings contains multiple hooks for event
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/27dfbc57dd30f8b6.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/memory-vault.js:688
const targetHarness = options.targetHarness
? validateSlug(options.targetHarness, 'target harness')
: null;
const loaded = readMemoryFiles(options);
if (loaded.truncated || loaded.invalidFileCount > 0) {
throw incompleteMemoryLookupError();
}
const matches = loaded.entries
.filter(entry => entry.memory.id === memoryId)
.filter(entry => (
!targetHarness
|| entry.memory.targetHarnesses.includes('all')
|| entry.memory.targetHarnesses.includes(targetHarness)
));
if (matches.length === 0) {
throw new Error(`Memory ${memoryId} was not found.`);
}
if (matches.length > 1) {
throw new Error(`Memory ${memoryId} is duplicated in ${matches.length} files.`);
}
const allBacklinks = loaded.entries
.filter(entry => entry.memory.links.includes(memoryId))
.filter(entry => entry.memory.status === 'active')
.map(entry => entry.memory)
.filter(memory => (
!targetHarness
|| memory.targetHarnesses.includes('all')
|| memory.targetHarnesses.includes(targetHarness)
))
.sort((left, right) => left.id.localeCompare(right.id));
const backlinks = allBacklinks
.slice(0, MAX_RESULTS)
.map(summarizeMemory);
return {
...matches[0],
backlinks,
backlinksTruncated: allBacklinks.length > backlinks.length,View on GitHub (pinned to 8321021c54)