affaan-m/ECC · error · Error

Memory ${memoryId} is duplicated in ${matches.length} files.

Error message

Memory ${memoryId} is duplicated in ${matches.length} files.

What it means

readMemoryById requires that an id maps to exactly one file. If two or more files in the scanned scopes share the same memory id (after applying the targetHarness filter), the vault refuses to pick one arbitrarily and throws a duplication error. This protects against ambiguous reads when the vault integrity invariant (one id -> one file) has been broken.

Source

Thrown at scripts/lib/memory-vault.js:673

function readMemoryById(id, options = {}) {
  const memoryId = validateMemoryId(id);
  const targetHarness = options.targetHarness
    ? validateSlug(options.targetHarness, 'target harness')
    : null;
  const loaded = readMemoryFiles(options);
  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 01e15490f0)

Solutions

  1. Run doctorMemoryVault to list every duplicate id and the offending file paths.
  2. Decide which copy is canonical, delete the others (rm <path>), and re-run readMemoryById.
  3. If both copies have unique content, re-save the non-canonical one with a new id (load it, saveMemory with a fresh id and a link to the survivor), then delete the original duplicate.
  4. Fix the upstream cause: stop syncing the vault with a file-level sync tool, or fix the idFactory that produced the collision.

Example fix

// diagnose
const report = doctorMemoryVault({});
console.log(report.duplicateIds); // [{ id: 'mem_x', paths: ['project:notes/mem_x.md', 'user:notes/mem_x.md'] }]
// fix: remove the non-canonical copy
fs.unlinkSync('<user-root>/notes/mem_x.md');
const mem = readMemoryById('mem_x'); // now resolves uniquely
Defensive patterns

Strategy: validation

Validate before calling

const { doctorMemoryVault } = require('./scripts/lib/memory-vault');
function assertNoDuplicateIds(options = {}) {
  const report = doctorMemoryVault(options);
  if (report.duplicateIdCount > 0) {
    throw new Error(`Duplicate memory ids detected: ${report.duplicateIds.map(d => d.id).join(', ')}`);
  }
}
// before readMemoryById:
assertNoDuplicateIds(options);

Try / catch

try { return readMemoryById(id, options); }
catch (error) {
  if (/is duplicated in/.test(error.message)) {
    const report = doctorMemoryVault(options);
    console.error('Resolve duplicates:', report.duplicateIds);
    return null;
  }
  throw error;
}

Prevention

When it happens

Trigger: Two .md files under the scanned vault roots parse to memories with identical id fields. Caused by a buggy save that wrote the same id twice, a manual copy/paste of a memory file, a botched vault merge, or a sync conflict that created a duplicate. doctorMemoryVault reports the same condition in its duplicateIds diagnostic.

Common situations: Sync conflicts (Syncthing/Dropbox) creating mem_x.md and mem_x (1).md both with the same id; manually copying a memory file to a second scope without changing the id; a race in a custom idFactory; merging two users' vaults by copying files.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/27dfbc57dd30f8b6. Report an issue: GitHub.