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
- Lowercase the value and replace spaces/punctuation with hyphens.
- Ensure the first character is a lowercase letter or digit.
- 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
- Generate slugs from display names with a deterministic slugify function.
- Validate slug fields in the form before submission.
- Never store display names in slug fields; keep them separate.
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
- ${label} must be a non-empty string.
- memory id must match mem_<lowercase-id> and cannot contain a
- ${label} must be an array.
- Invalid format: ${parsed.format}. Use text, json, or markdow
- ${label} is too long (maximum ${maxChars} characters).
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/7932c0548219bc85.
Report an issue: GitHub.