affaan-m/ECC · error · Error

${label} must be a lowercase letters/numbers slug.

Error message

${label} must be a lowercase letters/numbers slug.

What it means

Thrown by validateSlug() when the trimmed value does not match SLUG_PATTERN (/^[a-z0-9][a-z0-9._-]{0,63}$/). Slugs must start with a lowercase letter or digit, contain only lowercase alphanumerics, dot, underscore, or hyphen, and be at most 64 chars. Used for tag slugs, target harness identifiers, and similar keyed fields.

Source

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

  }
  if (hasUnsafeControlCharacters(normalized)) {
    throw new Error(`${label} must not contain control or bidirectional formatting characters.`);
  }
  return normalized;
}

function validateEnum(value, allowed, label) {
  const normalized = asNonEmptyString(value, label, 64);
  if (!allowed.includes(normalized)) {
    throw new Error(`${label} must be one of: ${allowed.join(', ')}.`);
  }
  return normalized;
}

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}).`);

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Lowercase the value and replace spaces/punctuation with hyphens.
  2. Ensure the first character is a lowercase letter or digit.
  3. Keep the slug to 64 characters or fewer.

Example fix

// before
validateSlug('REST API Notes', 'tag');
// after
validateSlug('rest-api-notes', 'tag');
Defensive patterns

Strategy: validation

Validate before calling

const SLUG = /^[a-z0-9][a-z0-9._-]{0,63}$/;
function toSlug(value) {
  return String(value).toLowerCase().trim().replace(/[^a-z0-9._-]+/g, '-').replace(/^-+/,'').slice(0, 64);
}
function isValidSlug(value) { return SLUG.test(value); }

Type guard

function isSlug(value) {
  return typeof value === 'string' && /^[a-z0-9][a-z0-9._-]{0,63}$/.test(value);
}

Try / catch

try {
  result = validateSlug(value, label);
} catch (e) {
  if (/lowercase letters\/numbers slug/.test(e.message)) {
    result = validateSlug(toSlug(value), label);
  } else throw e;
}

Prevention

When it happens

Trigger: Passing 'My Tag', 'tag with space', 'UPPER', a slug starting with a hyphen, or a slug longer than 64 characters.

Common situations: User-typed tags with capitalization or spaces; copy-pasting a display name where a slug is required; generated slugs that include forbidden punctuation.

Related errors


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