{"record":{"id":"6035cf848a6f7cab","repo":"affaan-m/ECC","slug":"label-must-be-a-non-empty-string","errorCode":null,"errorMessage":"${label} must be a non-empty string.","messagePattern":"(.+?) must be a non-empty string\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/memory-vault-format.js","lineNumber":79,"sourceCode":"\nfunction hasUnsafeControlCharacters(value, allowBodyWhitespace = false) {\n  return Array.from(value).some(character => {\n    const codePoint = character.codePointAt(0);\n    const allowedWhitespace = allowBodyWhitespace\n      && (codePoint === 0x09 || codePoint === 0x0a || codePoint === 0x0d);\n    const isControl = (codePoint <= 0x1f && !allowedWhitespace)\n      || (codePoint >= 0x7f && codePoint <= 0x9f);\n    const isBidirectionalFormatting = (\n      (codePoint >= 0x202a && codePoint <= 0x202e)\n      || (codePoint >= 0x2066 && codePoint <= 0x2069)\n    );\n    return isControl || isBidirectionalFormatting;\n  });\n}\n\nfunction asNonEmptyString(value, label, maxChars = 10_000) {\n  if (typeof value !== 'string' || value.trim().length === 0) {\n    throw new Error(`${label} must be a non-empty string.`);\n  }\n  const normalized = value.trim();\n  if (normalized.length > maxChars) {\n    throw new Error(`${label} is too long (maximum ${maxChars} characters).`);\n  }\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}","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/memory-vault-format.js#L61-L97","documentation":"asNonEmptyString is the shared validator in the memory-vault format layer. Every labeled field (title, content, etc.) must be a string that is non-empty after trimming; anything else — non-strings, whitespace-only values — is rejected with a message naming the field via the label parameter.","triggerScenarios":"Calling asNonEmptyString(value, label) (directly or via normalizeMemory/resolveOverride) with undefined, null, a number, or a string like '   ' whose trim().length is 0.","commonSituations":"A memory record saved with an empty title/content field; JSON round-trips turning a value into null; form or CLI input left blank; an optional field assumed to have a default but actually undefined.","solutions":["Supply a non-empty string for the labeled field before calling.","Trim-check the input in the UI/CLI layer and prompt again when blank.","Fall back to a sensible default for optional fields instead of passing undefined.","Ensure values read from JSON are strings, not null."],"exampleFix":"// before\nnormalizeMemory({ title: req.body.title })  // title: undefined\n// after\nnormalizeMemory({ title: (req.body.title || '').trim() || 'Untitled' })","handlingStrategy":"validation","validationCode":"function requireNonEmptyString(v, fallback) {\n  const s = typeof v === 'string' ? v.trim() : ''\n  if (!s) return fallback ?? (() => { throw new Error('Field is required') })()\n  return s\n}","typeGuard":"function isNonEmptyString(v) {\n  return typeof v === 'string' && v.trim().length > 0\n}\nif (!isNonEmptyString(input.title)) throw new TypeError('title must be a non-empty string')","tryCatchPattern":"try {\n  const memory = normalizeMemory(raw)\n} catch (err) {\n  if (err.message.endsWith('must be a non-empty string.')) {\n    console.error(`Missing field: ${err.message.split(' ')[0]} — prompt the user or apply a default`)\n  } else throw err\n}","preventionTips":["Trim and check user input before creating vault records.","Provide defaults for optional fields instead of undefined.","Validate JSON-loaded records: nulls are common after round-trips.","Require required fields at the form/CLI layer, not only at the library boundary."],"tags":["validation","memory-vault","empty-input"],"backgroundTag":"empty-required-field","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"}