{"record":{"id":"7932c0548219bc85","repo":"affaan-m/ECC","slug":"label-must-be-a-lowercase-letters-numbers-slug","errorCode":null,"errorMessage":"${label} must be a lowercase letters/numbers slug.","messagePattern":"(.+?) must be a lowercase letters/numbers slug\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/memory-vault-format.js","lineNumber":102,"sourceCode":"  }\n  if (hasUnsafeControlCharacters(normalized)) {\n    throw new Error(`${label} must not contain control or bidirectional formatting characters.`);\n  }\n  return normalized;\n}\n\nfunction validateEnum(value, allowed, label) {\n  const normalized = asNonEmptyString(value, label, 64);\n  if (!allowed.includes(normalized)) {\n    throw new Error(`${label} must be one of: ${allowed.join(', ')}.`);\n  }\n  return normalized;\n}\n\nfunction validateSlug(value, label) {\n  const normalized = asNonEmptyString(value, label, 64);\n  if (!SLUG_PATTERN.test(normalized)) {\n    throw new Error(`${label} must be a lowercase letters/numbers slug.`);\n  }\n  return normalized;\n}\n\nfunction 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}).`);","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/memory-vault-format.js#L84-L120","documentation":"validateSlug enforces that a slug-like field (e.g. source harness, tag scope identifiers) is a non-empty string of at most 64 characters matching /^[a-z0-9][a-z0-9._-]{0,63}$/ — lowercase letters, digits, dots, underscores, hyphens only, starting with a letter or digit. The library throws this to keep slugs safe for use as file names and identifiers in the memory vault, blocking uppercase text, spaces, and path characters like '/'.","triggerScenarios":"Calling normalizeMemory with a source_harness/target harness value, or any code path calling validateSlug(value, label) where value is e.g. 'Claude Code' (uppercase/space), '/etc/passwd', '', or a 65+ character string.","commonSituations":"Hand-written frontmatter with CamelCase harness names like 'Claude-Code'; slugs copy-pasted from URLs containing uppercase or '%20'; slugs accidentally containing a slash producing a path-traversal risk; a locale or encoder uppercasing the value.","solutions":["Lowercase the value and replace every character outside [a-z0-9._-] with '-' (trim leading/trailing separators is optional, first char must be [a-z0-9]).","Ensure the value is a string, not a number or object; coerce with String(value) first if needed.","Shorten the slug to 64 characters or fewer.","If the value is meant to be an id, use validateMemoryId's mem_ format instead."],"exampleFix":"// before\nnormalizeMemory({ sourceHarness: 'Claude Code', ... })\n// after\nnormalizeMemory({ sourceHarness: 'claude-code', ... })","handlingStrategy":"validation","validationCode":"function isValidSlug(v) { return typeof v === 'string' && /^[a-z0-9][a-z0-9._-]{0,63}$/.test(v); }\nif (!isValidSlug(harness)) throw new Error('bad slug: ' + harness);","typeGuard":"const isSlug = (v) => typeof v === 'string' && /^[a-z0-9][a-z0-9._-]{0,63}$/.test(v);","tryCatchPattern":"try { normalizeMemory(mem); } catch (e) { if (e.message.includes('must be a lowercase letters/numbers slug')) { mem.sourceHarness = slugify(mem.sourceHarness); } else throw e; }","preventionTips":["Slugify all identifiers at ingestion: v.toLowerCase().replace(/[^a-z0-9._-]+/g, '-')","Add a unit test for every config field that feeds a slug","Never build slugs from user-visible names without normalization","Lint frontmatter files with the same regex in CI"],"tags":["validation","slug","memory-vault"],"backgroundTag":"invalid-argument-format","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"}