affaan-m/ECC · error

must be an array.

Error message

${label} must be an array.

What it means

uniqueStrings requires its first argument to be a JavaScript Array; the library throws this error when a list field (tags, links, target harnesses, scopes) is passed as any other type. It guarantees downstream reduce() iteration is safe and every list field in a memory document has a consistent array shape.

Solutions

  1. Wrap the single value in an array: 'claude-code' -> ['claude-code'].
  2. Split comma-separated strings explicitly before passing: value.split(',').map(s => s.trim()).
  3. Ensure the field is present and defaults to [] rather than null/undefined.
  4. Convert Set/Map iterables with Array.from(value) if the source is an iterable.

Example fix

// before
normalizeMemory({ tags: 'general, tdd', ... })
// after
normalizeMemory({ tags: ['general', 'tdd'], ... })
Defensive patterns

Strategy: type-guard

Validate before calling

if (!Array.isArray(mem.tags)) mem.tags = mem.tags == null ? [] : [mem.tags];

Type guard

const isStringArray = (v) => Array.isArray(v) && v.every((x) => typeof x === 'string');

Try / catch

try { normalizeMemory(mem); } catch (e) { if (e.message.includes('must be an array')) { throw new Error('Field must be a list in frontmatter, e.g. tags: [a, b]'); } throw e; }

Prevention

When it happens

Trigger: Passing a non-array to targetHarnesses, normalizeMemory list fields, normalizeScopes, or the kinds helper — e.g. a comma-separated string 'a,b', a Set, null, undefined, or an object mapping names to values.

Common situations: Frontmatter YAML parsed with a scalar instead of a list (tags: general instead of tags: [general]); JSON configs where a single item was given without array brackets; deserialization frameworks returning Set or Map instead of Array; a field omitted and defaulted to null.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/09d7bbcdd9254660. Report an issue: GitHub.

Appendix: source

Thrown at scripts/lib/memory-vault-format.js:117

function validateSlug(value, label) {
  const normalized = asNonEmptyString(value, label, 64);
  if (!SLUG_PATTERN.test(normalized)) {
    throw new Error(`${label} must be a lowercase letters/numbers slug.`);
  }
  return normalized;
}

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)

View on GitHub (pinned to 8321021c54)