MemPalace/mempalace · error · ValueError

{field_name} exceeds maximum length of {_MAX_ROUTING_LENGTH}

Error message

{field_name} exceeds maximum length of {_MAX_ROUTING_LENGTH} characters

What it means

ValueError raised by _sanitize_routing() when a routing field exceeds _MAX_ROUTING_LENGTH (256 characters). Routing fields become part of stream/room identifiers, so unbounded values are rejected to keep names and any derived paths/files manageable.

Source

Thrown at mempalace/logstream.py:114

    return f"{prefix}_{stamp}_{secrets.token_hex(6)}"


def _sanitize_routing(value, field_name: str, required: bool = True) -> Optional[str]:
    """Validate a short routing field (stream, room, agent, correlation_id).

    Streams may contain ``/`` (``project/mempalace``), so this is looser
    than ``config.sanitize_name`` — but null bytes, control characters,
    and over-length values are still rejected.
    """
    if value is None or value == "":
        if required:
            raise ValueError(f"{field_name} must be a non-empty string")
        return None
    if not isinstance(value, str) or not value.strip():
        raise ValueError(f"{field_name} must be a non-empty string")
    value = strip_lone_surrogates(value.strip())
    if len(value) > _MAX_ROUTING_LENGTH:
        raise ValueError(f"{field_name} exceeds maximum length of {_MAX_ROUTING_LENGTH} characters")
    if any(ord(ch) < 0x20 or ch == "\x7f" for ch in value):
        raise ValueError(f"{field_name} contains control characters")
    return value


def _sanitize_event_type(value) -> str:
    if not isinstance(value, str) or not value.strip():
        raise ValueError("type must be a non-empty string")
    value = value.strip()
    if not _EVENT_TYPE_RE.match(value):
        raise ValueError(
            f"type={value!r} is not a valid event type "
            "(lowercase letters, digits, '.', '_', '-'; max 64 chars)"
        )
    return value


def _sanitize_status(value) -> Optional[str]:

View on GitHub (pinned to 06cb6987f0)

Solutions

  1. Shorten the value to <= 256 chars — routing fields are names, not payloads
  2. Move long content into the event payload/body fields, which are not routing-limited
  3. If generating names programmatically, hash the long part: hashlib.sha256(x.encode()).hexdigest()[:16]

Example fix

# before
events.emit(type="x", stream="project/" + "a" * 400, room="r")  # exceeds maximum length of 256

# after
import hashlib
short = hashlib.sha256(long_name.encode()).hexdigest()[:16]
events.emit(type="x", stream=f"project/{short}", room="r")
Defensive patterns

Strategy: validation

Validate before calling

MAX_ROUTING = 256

def routing_ok(value) -> bool:
    return isinstance(value, str) and 0 < len(value.strip()) <= MAX_ROUTING

Try / catch

try:
    events.emit(type=t, stream=s, room=r)
except ValueError as e:
    if "exceeds maximum length" in str(e):
        s = s[:MAX_ROUTING]
        events.emit(type=t, stream=s, room=r)
    else:
        raise

Prevention

When it happens

Trigger: Passing a long descriptive string, a full sentence, or concatenated identifiers (e.g. 'wing/room/drawer/uuid/uuid/uuid...') as stream, room, agent, or correlation_id with length > 256.

Common situations: Stuffing a path or message snippet into correlation_id; auto-generated names that concatenate many ids; pasting a whole line of output into a routing field by mistake.

Related errors


AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15). Data as JSON: /api/errors/54b524e392fa166a. Report an issue: GitHub.