{"record":{"id":"83cd1e28ed507ac7","repo":"MemPalace/mempalace","slug":"field-name-contains-invalid-characters","errorCode":null,"errorMessage":"{field_name} contains invalid characters","messagePattern":"(.+?) contains invalid characters","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"mempalace/config.py","lineNumber":96,"sourceCode":"    if not isinstance(value, str) or not value.strip():\n        raise ValueError(f\"{field_name} must be a non-empty string\")\n\n    value = value.strip()\n\n    if len(value) > MAX_NAME_LENGTH:\n        raise ValueError(f\"{field_name} exceeds maximum length of {MAX_NAME_LENGTH} characters\")\n\n    # Block path traversal\n    if \"..\" in value or \"/\" in value or \"\\\\\" in value:\n        raise ValueError(f\"{field_name} contains invalid path characters\")\n\n    # Block null bytes\n    if \"\\x00\" in value:\n        raise ValueError(f\"{field_name} contains null bytes\")\n\n    # Enforce safe character set\n    if not _SAFE_NAME_RE.match(value):\n        raise ValueError(f\"{field_name} contains invalid characters\")\n\n    return value\n\n\ndef sanitize_kg_value(value: str, field_name: str = \"value\") -> str:\n    \"\"\"Validate a knowledge-graph entity name (subject or object).\n\n    More permissive than sanitize_name — allows punctuation like commas,\n    colons, and parentheses that are common in natural-language KG values.\n    Only blocks null bytes and over-length strings.\n\n    Not used for wing/room names (which have filesystem constraints) or\n    predicates (which should be simple relationship identifiers).\n    \"\"\"\n    if not isinstance(value, str) or not value.strip():\n        raise ValueError(f\"{field_name} must be a non-empty string\")\n\n    value = value.strip()","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/MemPalace/mempalace/blob/06cb6987f02610784fefbad4b2bd5d026d164ba6/mempalace/config.py#L78-L114","documentation":"Raised by sanitize_name() when the name contains characters outside the safe-name character set defined by _SAFE_NAME_RE in mempalace/config.py. Wing/room names become filesystem directories and storage ids, so only a conservative allowed set (broadly: letters, digits, underscore, hyphen, space, and similar safe punctuation) is permitted; anything else — punctuation like ':' or '*', control chars, emoji in some configs — is rejected.","triggerScenarios":"Passing a name with characters not matched by _SAFE_NAME_RE, e.g. \"room:1\", \"bug*fix\", names with control characters, or other symbols; the exact allowed set is whatever the compiled regex in config.py permits.","commonSituations":"Natural-language titles with punctuation used as names; LLM-generated names with colons or asterisks; locale-specific characters not covered by the safe set; copy-paste introducing invisible control characters.","solutions":["Normalize the name to the safe slug style the library itself uses: lowercase, spaces/hyphens to underscores (see the slug helper above sanitize_name in config.py)","Check the _SAFE_NAME_RE pattern in your installed mempalace/config.py to know the exact allowed set","Move punctuation-heavy display titles into content/metadata and use a clean slug as the name"],"exampleFix":"# before\ncreate_room(\"Room: #1 (draft)*\")\n\n# after\ncreate_room(\"room_1_draft\")","handlingStrategy":"validation","validationCode":"# Normalize to the library's own slug convention before calling:\nname = name.lower().replace(\" \", \"_\").replace(\"-\", \"_\").strip(\"_\")\n# then check the safe set with the same rule the library uses","typeGuard":"from mempalace.config import _SAFE_NAME_RE  # if exported/accessible\n\ndef is_safe_name(value: str) -> bool:\n    return bool(_SAFE_NAME_RE.match(value.strip())) if hasattr(globals().get('_SAFE_NAME_RE', None), 'match') else None\n# Prefer copying the regex from your installed config.py into your validator.","tryCatchPattern":"try:\n    safe = sanitize_name(name)\nexcept ValueError as exc:\n    if \"invalid characters\" in str(exc):\n        safe = sanitize_name(re.sub(r\"[^\\w\\- ]\", \"_\", name))\n    else:\n        raise","preventionTips":["Slugify names (lowercase, underscores) at your app boundary","Keep punctuation-heavy titles in content/metadata, not names","Copy _SAFE_NAME_RE from your installed mempalace/config.py into client-side validation so rules stay in sync"],"tags":["validation","names","character-set","mempalace"],"backgroundTag":null,"analyzedSha":"06cb6987f02610784fefbad4b2bd5d026d164ba6","analyzedAt":"2026-08-15T03:03:36.213Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}