MemPalace/mempalace · error · ValueError
status={value!r} is not one of: {allowed}
Error message
status={value!r} is not one of: {allowed} What it means
The `status` field of append_event/ack_event must be one of the fixed lifecycle set EVENT_STATUSES = {'open','claimed','ready','applied','blocked','failed','superseded'} (or None/'' to omit). Any other string — including near-misses like 'done', 'OK', 'claimed ' with a space — is rejected with the allowed list echoed in the message. Statuses are a controlled vocabulary so agents can filter reliably.
Source
Thrown at mempalace/logstream.py:137
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]:
if value is None or value == "":
return None
if not isinstance(value, str) or value not in EVENT_STATUSES:
allowed = ", ".join(sorted(EVENT_STATUSES))
raise ValueError(f"status={value!r} is not one of: {allowed}")
return value
def _sanitize_body(value, max_bytes: int, field_name: str = "body") -> str:
"""Validate verbatim payload text. Empty is allowed; ``None`` becomes ''."""
if value is None:
return ""
if not isinstance(value, str):
raise ValueError(f"{field_name} must be a string")
if "\x00" in value:
raise ValueError(f"{field_name} contains null bytes")
value = strip_lone_surrogates(value)
size = len(value.encode("utf-8"))
if size > max_bytes:
raise ValueError(f"{field_name} is {size} bytes; maximum is {max_bytes} bytes")
return value
View on GitHub (pinned to 06cb6987f0)
Solutions
- Use one of the exact allowed values: open, claimed, ready, applied, blocked, failed, superseded.
- Map external statuses to the enum before calling (e.g. 'Closed' -> 'applied', 'In Review' -> 'claimed').
- Pass status=None or omit it when there is no lifecycle state to record.
Example fix
// before ls.append_event(type="task.request", status="Done", ...) // after ls.append_event(type="task.request", status="applied", ...)
Defensive patterns
Strategy: validation
Validate before calling
from mempalace.logstream import EVENT_STATUSES
def normalize_status(s):
if s is None or s == "":
return None
s = str(s).strip().lower()
aliases = {"done": "applied", "ok": "applied", "in_progress": "claimed", "closed": "applied"}
return aliases.get(s, s) if s in EVENT_STATUSES or s in aliases else None
status = normalize_status(raw_status)
if raw_status and status is None:
raise ValueError(f"unmappable status {raw_status!r}") Type guard
from mempalace.logstream import EVENT_STATUSES
def is_valid_status(s) -> bool:
return s is None or s == "" or (isinstance(s, str) and s in EVENT_STATUSES) Try / catch
try:
evt = ls.append_event(..., status=status)
except ValueError as e:
if "not one of" in str(e) and "status=" in str(e):
evt = ls.append_event(..., status=None) # drop rather than fail the event
else:
raise Prevention
- Import EVENT_STATUSES from mempalace.logstream and validate against it instead of hardcoding the list.
- Map external tracker statuses to the enum at the adapter layer, never inside event-writing code.
- Reject unmappable statuses loudly at ingestion so bad vocabularies surface early.
When it happens
Trigger: append_event(status='done'), status='In Progress', status='claimed!' from an LLM-generated payload, or ack_event(status='ok'). Passing a non-string such as status=0 or status=True also triggers it (isinstance check comes second).
Common situations: LLM agents freestyle a status word instead of the enum; callers mapping tickets from external trackers (Jira 'In Review', 'Closed') directly into the logstream; casing or spelling drift between producer versions.
Related errors
- kind={kind!r} is not one of: {allowed}
- {field_name} must be a non-empty string
- {field_name} exceeds maximum length of {_MAX_ROUTING_LENGTH}
- {field_name} contains control characters
- type must be a non-empty string
AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15).
Data as JSON: /api/errors/c393fcabd34c905c.
Report an issue: GitHub.