affaan-m/ECC · error · Error
${label} must not contain duplicate values.
Error message
${label} must not contain duplicate values. What it means
Thrown by uniqueStrings() when two entries in the input array normalize to the same value (the validator is applied before the duplicate check). It enforces a set semantic for list fields so storage and lookup are deterministic.
Source
Thrown at scripts/lib/memory-vault-format.js:125
function validateMemoryId(value) {
const normalized = asNonEmptyString(value, 'memory id', 132);
if (!MEMORY_ID_PATTERN.test(normalized)) {
throw new Error('memory id must match mem_<lowercase-id> and cannot contain a path.');
}
return normalized;
}
function uniqueStrings(values, { label, limit, validator }) {
if (!Array.isArray(values)) {
throw new Error(`${label} must be an array.`);
}
if (values.length > limit) {
throw new Error(`${label} has too many values (maximum ${limit}).`);
}
return values.reduce((result, value) => {
const normalized = validator(value);
if (result.includes(normalized)) {
throw new Error(`${label} must not contain duplicate values.`);
}
return [...result, normalized];
}, []);
}
function validateTimestamp(value, label) {
const normalized = asNonEmptyString(value, label, 64);
const parsed = new Date(normalized);
if (
!ISO_TIMESTAMP_PATTERN.test(normalized)
|| Number.isNaN(parsed.getTime())
|| parsed.toISOString() !== normalized
) {
throw new Error(`${label} must be an ISO-8601 timestamp.`);
}
return normalized;
}
View on GitHub (pinned to 01e15490f0)
Solutions
- Dedupe the array (e.g. [...new Set(values)]) before passing it in.
- Remember the validator may normalize (lowercase, trim) before the duplicate check runs.
- Audit the upstream producer if duplicates keep appearing.
Example fix
// before
uniqueStrings(['api', 'api', 'auth'], { label: 'tags', limit: 32, validator: v => v.toLowerCase() });
// after
uniqueStrings([...new Set(['api', 'api', 'auth'])], { label: 'tags', limit: 32, validator: v => v.toLowerCase() }); Defensive patterns
Strategy: validation
Validate before calling
function dedupe(values) {
return [...new Set(values)];
}
// pass deduped array to uniqueStrings to avoid the duplicate guard firing:
result = uniqueStrings(dedupe(values), opts); Type guard
function hasNoDuplicates(values) {
return Array.isArray(values) && new Set(values).size === values.length;
} Try / catch
try {
result = uniqueStrings(values, opts);
} catch (e) {
if (/must not contain duplicate values/.test(e.message)) {
result = uniqueStrings([...new Set(values)], opts);
} else throw e;
} Prevention
- Always dedupe list inputs before submission.
- Remember normalization (lowercase/trim) can create duplicates from visually distinct inputs.
- When merging documents, run a dedupe pass on tag/link lists.
When it happens
Trigger: Passing ['tag-a', 'tag-a'], ['TAG-A', 'tag-a'] when the validator lowercases, or two slugs that trim to the same value.
Common situations: Merging tag lists from multiple sources without dedup; case-sensitive copy-paste that produces near-duplicates after normalization.
Related errors
- ${label} must be an array.
- ${label} has too many values (maximum ${limit}).
- Duplicate memory frontmatter field in ${sourcePath}.
- Invalid ECC repo root: missing package.json at ${packageJson
- Invalid ECC repo root: missing install script at ${installAp
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/7af48005559c46eb.
Report an issue: GitHub.