{"record":{"id":"7f5dc63e128c68ea","repo":"JuliusBrussee/caveman","slug":"payload-limit-7f5dc6","errorCode":"payload_limit","errorMessage":"payload_limit","messagePattern":"payload_limit","errorType":"error_code","errorClass":"MiddlewareError","httpStatus":null,"severity":"error","filePath":"packages/sdk/python/caveman_cloud/middleware/runtime.py","lineNumber":398,"sourceCode":"\n            bound()\n            connection.request(\"POST\" if body is not None else \"GET\", PREFIX + path,\n                               body=body.encode(\"utf-8\") if body is not None else None, headers=headers)\n            bound()\n            with connection.getresponse() as response:\n                if 300 <= response.status < 400:\n                    raise MiddlewareError(\"redirect_refused\")\n                content = bytearray()\n                while True:\n                    bound()\n                    # read1 plus the remaining socket deadline bounds slow,\n                    # chunked bodies without buffering beyond the response cap.\n                    part = response.read1(min(65536, (4 << 20) + 1 - len(content)))\n                    if not part:\n                        break\n                    content.extend(part)\n                    if len(content) > 4 << 20:\n                        raise MiddlewareError(\"payload_limit\")\n                data = json.loads(content.decode(\"utf-8\"))\n                if not 200 <= response.status < 300:\n                    code = data.get(\"error\", {}).get(\"code\") if isinstance(data, dict) else None\n                    raise MiddlewareError(code if validate.token(code) else \"runtime_unavailable\")\n                return data\n        finally:\n            connection.close()\n            with self._lock:\n                self._connections.discard(connection)\n","sourceCodeStart":380,"sourceCodeEnd":408,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/sdk/python/caveman_cloud/middleware/runtime.py#L380-L408","documentation":"MiddlewareError raised by _http when the response body exceeds the hard 4 MiB cap (4 << 20 bytes). The transport streams with read1 and aborts as soon as buffered content would exceed the limit, to prevent unbounded memory use from a misbehaving or hostile server.","triggerScenarios":"Any of ready()/optimize()/retrieve()/observe()/delete_session() receiving a JSON response larger than 4 MiB, or a server that never terminates the body (slow-loris style) until the cap trips.","commonSituations":"retrieve() on a very large document whose recovery page exceeds 4 MiB; observe() batch payloads too large; a misconfigured or buggy middleware returning an error page/HTML larger than the cap; proxy appending large bodies.","solutions":["Reduce request size: narrow the optimize/retrieve scope or paginate results so each response stays under 4 MiB","If you control the middleware, lower per-request result size or raise the client cap (4 MiB constant in runtime.py) consciously","Check the server for loops/bugs that emit unbounded or non-JSON bodies","Capture the response with curl to confirm actual body size before adjusting limits"],"exampleFix":"// before\nresult = client.retrieve(handle)  # 6 MiB page -> payload_limit\n// after\nresult = client.retrieve(handle, page_offset=0)  # paginate, each page < 4 MiB","handlingStrategy":"try-catch","validationCode":"# estimate response size beforehand when the API exposes counts\n# e.g. skip retrieve if projected page size exceeds 4 MiB\nif estimated_bytes > 4 * 1024 * 1024:\n    use_pagination = True","typeGuard":"def fits_payload_cap(n_bytes: int, cap: int = 4 << 20) -> bool:\n    return 0 < n_bytes <= cap","tryCatchPattern":"try:\n    data = client.retrieve(handle)\nexcept MiddlewareError as e:\n    if e.args[0] == \"payload_limit\":\n        data = fetch_in_pages(handle)  # retry with pagination\n    else:\n        raise","preventionTips":["Design retrieve/observe calls to stay well under 4 MiB per response","Paginate large documents instead of requesting monolithic pages","Monitor middleware response sizes in logs to catch growth before it hits the cap","Don't disable the cap; raise it consciously only if you control both ends"],"tags":["network","http","payload","limit","python"],"backgroundTag":"payload-too-large","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}