MemPalace/mempalace · error · ValueError
kind={kind!r} is not one of: {allowed}
Error message
kind={kind!r} is not one of: {allowed} What it means
put_artifact rejects the `kind` argument because it is not in ARTIFACT_KINDS = {'patch','file','log','json','note'}. Kinds are a controlled vocabulary describing payload shape (a diff, a whole file, a captured log, structured JSON, or a free note) so consumers can pick handlers; the allowed set is printed in the error.
Source
Thrown at mempalace/logstream.py:523
def put_artifact(
self,
kind: str,
content: str,
created_by: str,
metadata: dict = None,
) -> dict:
"""Store exact artifact content (v1: UTF-8 text only).
Returns the artifact record without echoing ``content`` back —
callers already hold the content; readers use :meth:`get_artifact`.
For ``kind=patch``, a ``warnings`` list is included when the diff
looks unappliable (missing trailing newline, CRLF endings); the
content itself is still stored verbatim.
"""
if not isinstance(kind, str) or kind not in ARTIFACT_KINDS:
allowed = ", ".join(sorted(ARTIFACT_KINDS))
raise ValueError(f"kind={kind!r} is not one of: {allowed}")
created_by = _sanitize_routing(created_by, "created_by")
if not isinstance(content, str) or not content:
raise ValueError("content must be a non-empty string")
if "\x00" in content:
raise ValueError("content contains null bytes")
content = strip_lone_surrogates(content)
raw = content.encode("utf-8")
if len(raw) > self.max_artifact_bytes:
raise ValueError(
f"content is {len(raw)} bytes; maximum is {self.max_artifact_bytes} bytes"
)
metadata_json = _sanitize_metadata(metadata)
artifact_id = _new_id("art")
created_at = _utc_now_iso()
digest = sha256(raw).hexdigest()
with self._lock:View on GitHub (pinned to 06cb6987f0)
Solutions
- Use one of: patch, file, log, json, note (lowercase, exact).
- Pick by payload shape: unified diff -> 'patch', full file -> 'file', structured data -> 'json', captured output -> 'log', prose -> 'note'.
- Guard the call site against an upstream kind vocabulary: map or reject before invoking put_artifact.
Example fix
// before art = ls.put_artifact(kind="diff", content=diff_text, ...) // after art = ls.put_artifact(kind="patch", content=diff_text, ...)
Defensive patterns
Strategy: validation
Validate before calling
from mempalace.logstream import ARTIFACT_KINDS
def normalize_kind(kind):
k = str(kind).strip().lower()
aliases = {"diff": "patch", "text": "note", "data": "json", "output": "log"}
return aliases.get(k, k)
kind = normalize_kind(raw_kind)
assert kind in ARTIFACT_KINDS, f"unsupported kind {raw_kind!r}" Type guard
from mempalace.logstream import ARTIFACT_KINDS
def is_valid_kind(k) -> bool:
return isinstance(k, str) and k in ARTIFACT_KINDS Try / catch
try:
art = ls.put_artifact(kind=kind, content=content, ...)
except ValueError as e:
if "not one of" in str(e) and "kind=" in str(e):
art = ls.put_artifact(kind="note", content=content, ...) # generic fallback kind
else:
raise Prevention
- Import ARTIFACT_KINDS and validate/normalize at the edge where external kind vocabularies enter.
- Pin kind choice to payload shape (diff->patch, file->file, captured output->log, structured->json, prose->note).
When it happens
Trigger: put_artifact(kind='diff', ...) (should be 'patch'); kind='text' (should be 'note' or 'file'); kind='JSON' (case-sensitive); kind=None or a non-string; kind='binary' for payloads v1 does not support.
Common situations: LLM agents guessing kind names from the content instead of the enum; version drift after new kinds were added/renamed; casing copied from documentation headings.
Related errors
- status={value!r} is not one of: {allowed}
- content must be a non-empty string
- content contains null bytes
- content is {len(raw)} bytes; maximum is {self.max_artifact_b
- {field_name} must be a non-empty string
AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15).
Data as JSON: /api/errors/ea10da0ddbb3f36e.
Report an issue: GitHub.