ruvnet/RuView · error · Error

duplicate brain id: ${record.id}

Error message

duplicate brain id: ${record.id}

What it means

Record ids must be unique across the corpus; loadBrain tracks ids in a Set and throws, naming the duplicated id, when a later line reuses one. Ids are lowercase slugs, so independently written lessons about the same topic naturally collide.

Source

Thrown at harness/ruview/src/brain.js:57

  if (INJECTION.test(combined)) errors.push('record contains instruction-like prompt injection');
  return errors;
}

export function loadBrain(path = CORPUS_PATH) {
  const raw = readFileSync(path, 'utf8').replace(/\r\n/g, '\n');
  if (Buffer.byteLength(raw) > 1_048_576) throw new Error('brain corpus exceeds 1 MiB');
  const records = raw.split('\n').filter(Boolean).map((line, index) => {
    if (Buffer.byteLength(line) > 16_384) throw new Error(`brain line ${index + 1}: exceeds 16 KiB`);
    let record;
    try { record = JSON.parse(line); } catch (error) { throw new Error(`brain line ${index + 1}: ${error.message}`); }
    const errors = validateBrainRecord(record, { canonical: true });
    if (errors.length) throw new Error(`brain line ${index + 1}: ${errors.join('; ')}`);
    return Object.freeze(record);
  });
  if (records.length > 1000) throw new Error('brain corpus exceeds 1000 records');
  const ids = new Set();
  for (const record of records) {
    if (ids.has(record.id)) throw new Error(`duplicate brain id: ${record.id}`);
    ids.add(record.id);
  }
  return { records, digest: sha256(raw), bytes: Buffer.byteLength(raw) };
}

function terms(value) {
  return new Set(String(value).toLowerCase().match(/[a-z0-9][a-z0-9_-]{1,}/g) || []);
}

export function searchBrain(query, { limit = 8, path = CORPUS_PATH } = {}) {
  const wanted = terms(query);
  if (!wanted.size) return [];
  const { records, digest } = loadBrain(path);
  return records.map((record) => {
    const title = terms(record.title);
    const body = terms(record.content);
    const tags = new Set(record.tags.map((tag) => tag.toLowerCase()));
    let score = 0;

View on GitHub (pinned to 4685618388)

Solutions

  1. Rename the newer record's id to a distinct slug (e.g. append '-ci' or a qualifier)
  2. Locate both occurrences: grep -n '"id": "<duplicated-id>"' harness/ruview/brain/corpus/core.jsonl
  3. Prefer extending the existing record's content/tags over adding a near-duplicate

Example fix

// before (line 12 and line 48)
{"id":"cargo-timeout", ...}
{"id":"cargo-timeout", ...}

// after
{"id":"cargo-timeout", ...}
{"id":"cargo-timeout-ci", ...}
Defensive patterns

Strategy: validation

Validate before calling

import { readFileSync } from 'node:fs';
function duplicateIds(path) {
  const seen = new Set();
  const dupes = [];
  for (const line of readFileSync(path, 'utf8').split('\n')) {
    if (!line.trim()) continue;
    const id = JSON.parse(line).id;
    if (seen.has(id)) dupes.push(id); else seen.add(id);
  }
  return dupes;
}

Try / catch

try {
  const brain = loadBrain(path);
} catch (error) {
  if (error.message.startsWith('duplicate brain id')) {
    console.error(`id collision: ${error.message} — rename the newer record`);
    process.exit(1);
  }
  throw error;
}

Prevention

When it happens

Trigger: Copying an existing record line and editing the content without changing the id, or a git merge/cherry-pick that brings the same record in twice.

Common situations: Copy-modify authoring, duplicate records from parallel branches, two contributors adding the same lesson name.

Related errors


AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16). Data as JSON: /api/errors/dbcb5cb25c8f7c42. Report an issue: GitHub.