MemPalace/mempalace · warning · ValueError

request body too large

Error message

request body too large

What it means

ValueError('request body too large') raised in the daemon's HTTP handler (mempalace/daemon.py:938) when Content-Length exceeds MAX_BODY_BYTES. The cap bounds request memory use per authenticated request; the connection body is never read past the check. Like 208, this originates in the server and surfaces to a client as a 400 response with this message.

Source

Thrown at mempalace/daemon.py:938

        def log_message(self, fmt, *args):  # pragma: no cover - stdlib access logging noise
            return

        def _authorized(self) -> bool:
            auth = self.headers.get("Authorization")
            if auth and secrets.compare_digest(auth, f"Bearer {token}"):
                return True
            _json_response(self, 401, {"error": "unauthorized"})
            return False

        def _read_json(self) -> dict[str, Any]:
            length = int(self.headers.get("Content-Length", "0") or "0")
            # Reject a negative Content-Length explicitly: self.rfile.read(-1)
            # would read until the client closes the connection, blocking the
            # worker and bypassing the MAX_BODY_BYTES cap (an auth-gated DoS).
            if length < 0:
                raise ValueError("invalid Content-Length")
            if length > MAX_BODY_BYTES:
                raise ValueError("request body too large")
            raw = self.rfile.read(length)
            return json.loads(raw.decode("utf-8")) if raw else {}

        def do_GET(self):
            if not self._authorized():
                return
            try:
                self._handle_get()
            except Exception as exc:  # noqa: BLE001 - malformed query/DB error → 400
                _json_response(self, 400, {"error": str(exc)})

        def _handle_get(self):
            parsed = urlparse(self.path)
            if parsed.path == "/health":
                _json_response(
                    self,
                    200,
                    {

View on GitHub (pinned to 06cb6987f0)

Solutions

  1. Split the payload into smaller submits (chunk the transcript; see mempalace/split_mega_files.py for oversized transcript files).
  2. Trim needless fields from the payload before submitting.
  3. If a legitimate workflow needs a bigger cap, raise MAX_BODY_BYTES in daemon.py and restart — recognizing the larger memory commitment per request.

Example fix

# before: one giant submit
client.submit("save", {"content": huge_transcript})

# after: chunked submits
for chunk in chunks(huge_transcript, MAX_CHARS):
    client.submit("save", {"content": chunk})
Defensive patterns

Strategy: validation

Validate before calling

import json
from mempalace.daemon import MAX_BODY_BYTES

def fits(body: dict) -> bool:
    return len(json.dumps(body).encode("utf-8")) <= MAX_BODY_BYTES

Try / catch

try:
    resp = client.request("POST", "/jobs", payload)
except DaemonError as exc:
    if "too large" in str(exc):
        for chunk in split_payload(payload):
            client.request("POST", "/jobs", chunk)

Prevention

When it happens

Trigger: POSTing a large transcript/payload to /jobs (e.g. a whole conversation transcript as one submit) whose serialized JSON exceeds MAX_BODY_BYTES; batching many entries into one request; base64-encoding binary content into a JSON body inflating its size.

Common situations: Hook submits an unusually long session diary; users ingest mega-file transcripts (see split_mega_files.py) in a single call; generation of a huge dedupe key list.

Related errors


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