{"record":{"id":"7af48005559c46eb","repo":"affaan-m/ECC","slug":"label-must-not-contain-duplicate-values","errorCode":null,"errorMessage":"${label} must not contain duplicate values.","messagePattern":"(.+?) must not contain duplicate values\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/memory-vault-format.js","lineNumber":125,"sourceCode":"function validateMemoryId(value) {\n  const normalized = asNonEmptyString(value, 'memory id', 132);\n  if (!MEMORY_ID_PATTERN.test(normalized)) {\n    throw new Error('memory id must match mem_<lowercase-id> and cannot contain a path.');\n  }\n  return normalized;\n}\n\nfunction uniqueStrings(values, { label, limit, validator }) {\n  if (!Array.isArray(values)) {\n    throw new Error(`${label} must be an array.`);\n  }\n  if (values.length > limit) {\n    throw new Error(`${label} has too many values (maximum ${limit}).`);\n  }\n  return values.reduce((result, value) => {\n    const normalized = validator(value);\n    if (result.includes(normalized)) {\n      throw new Error(`${label} must not contain duplicate values.`);\n    }\n    return [...result, normalized];\n  }, []);\n}\n\nfunction validateTimestamp(value, label) {\n  const normalized = asNonEmptyString(value, label, 64);\n  const parsed = new Date(normalized);\n  if (\n    !ISO_TIMESTAMP_PATTERN.test(normalized)\n    || Number.isNaN(parsed.getTime())\n    || parsed.toISOString() !== normalized\n  ) {\n    throw new Error(`${label} must be an ISO-8601 timestamp.`);\n  }\n  return normalized;\n}\n","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/memory-vault-format.js#L107-L143","documentation":"uniqueStrings builds its result with a reduce that rejects any value whose normalized form already appeared earlier in the array, throwing this error. List fields in memory documents must be duplicate-free so tags/links/targets remain unambiguous.","triggerScenarios":"Passing an array with the same value twice (after per-item validator normalization) to targetHarnesses, normalizeMemory, normalizeScopes, or kinds — e.g. tags: ['tdd', 'TDD'] if the validator lowercases, or an exact duplicate ['tdd', 'tdd'].","commonSituations":"Merging tag lists from two documents without deduplication; appending to an existing array on each script run; copy-pasting frontmatter where a tag appears in two groups; case differences that normalize to the same value.","solutions":["Deduplicate before calling: Array.from(new Set(values)).","Deduplicate on the normalized form (e.g. lowercase/trim each element first) so near-duplicates collapse.","Fix the merge logic that appends items already present in the array.","Check the error label to identify which list field contains the duplicate."],"exampleFix":"// before\nnormalizeMemory({ tags: [...oldTags, ...newTags], ... })\n// after\nnormalizeMemory({ tags: [...new Set([...oldTags, ...newTags])], ... })","handlingStrategy":"validation","validationCode":"const dedupe = (arr) => Array.from(new Set(arr.map((s) => String(s).toLowerCase().trim())));","typeGuard":"const hasNoDuplicates = (v) => Array.isArray(v) && new Set(v).size === v.length;","tryCatchPattern":"try { normalizeMemory(mem); } catch (e) { if (e.message.includes('duplicate')) { mem.tags = dedupe(mem.tags); } else throw e; }","preventionTips":["Run new Set(values) on merged lists before saving","Normalize case/whitespace before comparing for duplicates","Make list-append operations idempotent","Test merge helpers with overlapping inputs"],"tags":["validation","duplicate","memory-vault"],"backgroundTag":"invalid-argument-value","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"}