{"record":{"id":"71ef0da0bf3dd89c","repo":"MemPalace/mempalace","slug":"metadata-exceeds-maximum-size-of-max-metadata-byt","errorCode":null,"errorMessage":"metadata exceeds maximum size of {MAX_METADATA_BYTES} bytes","messagePattern":"metadata exceeds maximum size of (.+?) bytes","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"mempalace/logstream.py","lineNumber":167,"sourceCode":"    value = strip_lone_surrogates(value)\n    size = len(value.encode(\"utf-8\"))\n    if size > max_bytes:\n        raise ValueError(f\"{field_name} is {size} bytes; maximum is {max_bytes} bytes\")\n    return value\n\n\ndef _sanitize_metadata(value) -> str:\n    \"\"\"Validate optional metadata dict and return its canonical JSON text.\"\"\"\n    if value is None:\n        return \"{}\"\n    if not isinstance(value, dict):\n        raise ValueError(\"metadata must be an object\")\n    try:\n        encoded = json.dumps(value, ensure_ascii=False, sort_keys=True)\n    except (TypeError, ValueError) as exc:\n        raise ValueError(f\"metadata is not JSON-serializable: {exc}\") from None\n    if len(encoded.encode(\"utf-8\")) > MAX_METADATA_BYTES:\n        raise ValueError(f\"metadata exceeds maximum size of {MAX_METADATA_BYTES} bytes\")\n    return encoded\n\n\nclass Logstream:\n    \"\"\"Durable append-only coordination log (events + artifacts).\n\n    Storage and threading mirror ``KnowledgeGraph``: one SQLite file in\n    WAL mode, a per-instance lock around writes, ``check_same_thread=False``\n    so the MCP HTTP server can call from worker threads.\n    \"\"\"\n\n    def __init__(\n        self,\n        db_path: str,\n        max_body_bytes: int = DEFAULT_MAX_BODY_BYTES,\n        max_artifact_bytes: int = DEFAULT_MAX_ARTIFACT_BYTES,\n        replica_id: str = None,\n    ):","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/MemPalace/mempalace/blob/06cb6987f02610784fefbad4b2bd5d026d164ba6/mempalace/logstream.py#L149-L185","documentation":"After canonical JSON serialization (ensure_ascii=False, sort_keys=True), the metadata exceeds MAX_METADATA_BYTES = 64 KiB. The limit applies to the encoded text, not the source dict, so Unicode content and key repetition count toward it. Metadata is an annotation layer, so the cap keeps event rows lean; large payloads belong in artifacts.","triggerScenarios":"metadata containing a long embedded string (e.g. {'context': 70_000-char prose}); large lists of ids; ensure_ascii=False means CJK metadata is counted at its real byte width (3 bytes/char) rather than \\\\uXXXX escapes.","commonSituations":"Agents stuffing entire prompt/response text into metadata 'for context'; metadata carrying full stack traces or base64 blobs; metadata grown gradually across versions until it crossed 64 KiB.","solutions":["Move the large value into put_artifact and keep only a pointer in metadata: metadata={'artifact_id': art['id']}.","Trim the metadata to the keys consumers actually read.","Check upfront: len(json.dumps(metadata, ensure_ascii=False, sort_keys=True).encode('utf-8')) <= 65536."],"exampleFix":"// before\nls.append_event(..., metadata={\"context\": huge_text})\n// after\nart = ls.put_artifact(kind=\"note\", content=huge_text, created_by=\"mac-codex\")\nls.append_event(..., metadata={\"context_artifact\": art[\"id\"]})","handlingStrategy":"validation","validationCode":"import json\nMAX_METADATA_BYTES = 64 * 1024\n\ndef metadata_fits(md) -> bool:\n    if md is None:\n        return True\n    encoded = json.dumps(md, ensure_ascii=False, sort_keys=True)\n    return len(encoded.encode(\"utf-8\")) <= MAX_METADATA_BYTES\n\nif not metadata_fits(md):\n    art = ls.put_artifact(kind=\"json\", content=json.dumps(md), created_by=who)\n    md = {\"artifact_id\": art[\"id\"]}","typeGuard":"def is_metadata_within_limit(md) -> bool:\n    return md is None or len(json.dumps(md, ensure_ascii=False, sort_keys=True).encode(\"utf-8\")) <= 64 * 1024","tryCatchPattern":"try:\n    evt = ls.append_event(..., metadata=metadata)\nexcept ValueError as e:\n    if \"exceeds maximum size\" in str(e):\n        art = ls.put_artifact(kind=\"json\", content=json.dumps(metadata), created_by=who)\n        evt = ls.append_event(..., metadata={\"artifact_id\": art[\"id\"]})\n    else:\n        raise","preventionTips":["Keep metadata to small scalars and short strings; move prose and blobs to artifacts.","Remember the 64 KiB applies to encoded bytes with ensure_ascii=False, so CJK keys/values count 3 bytes per char."],"tags":["validation","logstream","metadata","size-limit"],"backgroundTag":null,"analyzedSha":"06cb6987f02610784fefbad4b2bd5d026d164ba6","analyzedAt":"2026-08-15T03:03:36.213Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}