{"record":{"id":"d302f17a2d52acae","repo":"Hmbown/CodeWhale","slug":"exceeded-the-byte-aggregate-catalogue-limit","errorCode":null,"errorMessage":"{} exceeded the {}-byte aggregate catalogue limit","messagePattern":"(.+?) exceeded the (.+?)-byte aggregate catalogue limit","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/mcp.rs","lineNumber":1326,"sourceCode":"        self.pages = self.pages.saturating_add(1);\n        self.items = self.items.saturating_add(item_count);\n        self.bytes = self.bytes.saturating_add(serde_json::to_vec(result)?.len());\n        if self.pages > MAX_MCP_CATALOG_PAGES {\n            anyhow::bail!(\n                \"{} exceeded the {}-page catalogue limit\",\n                self.method,\n                MAX_MCP_CATALOG_PAGES\n            );\n        }\n        if self.items > MAX_MCP_CATALOG_ITEMS {\n            anyhow::bail!(\n                \"{} exceeded the {}-item catalogue limit\",\n                self.method,\n                MAX_MCP_CATALOG_ITEMS\n            );\n        }\n        if self.bytes > MAX_MCP_CATALOG_BYTES {\n            anyhow::bail!(\n                \"{} exceeded the {}-byte aggregate catalogue limit\",\n                self.method,\n                MAX_MCP_CATALOG_BYTES\n            );\n        }\n        let cursor = result\n            .get(\"nextCursor\")\n            .and_then(|value| value.as_str())\n            .map(str::to_owned);\n        if let Some(cursor) = cursor.as_ref()\n            && !self.seen_cursors.insert(cursor.clone())\n        {\n            anyhow::bail!(\"{} repeated pagination cursor; aborting\", self.method);\n        }\n        Ok(cursor)\n    }\n}\n","sourceCodeStart":1308,"sourceCodeEnd":1344,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/mcp.rs#L1308-L1344","documentation":"Third leg of McpCatalogBudget: the sum of serde-serialized page sizes across one catalogue method must stay within MAX_MCP_CATALOG_BYTES = 32 MiB (crates/tui/src/mcp.rs:1282, 1325-1331). Each page's JSON is serialized and its byte length accumulated; crossing 32 MiB aborts discovery. This bounds memory and prompt-bloat from very verbose catalogue entries.","triggerScenarios":"Fewer than 4096 items but each very large: multi-KB descriptions, embedded schemas or examples in tool definitions push the aggregate past 32 MiB.","commonSituations":"Auto-generated tool descriptions from OpenAPI specs; servers embedding full JSON Schemas with long examples per tool.","solutions":["Shorten tool/resource descriptions and trim JSON Schemas server-side.","Split the catalogue across multiple MCP servers so each stays under 32 MiB aggregate.","Remove example payloads and verbose metadata from catalogue entries."],"exampleFix":"# before (server): each tool carries a ~10 KB description -> 3500 tools ~ 35 MB\n# after (server): cap descriptions at ~500 chars -> aggregate well under 32 MiB","handlingStrategy":"validation","validationCode":"#!/usr/bin/env bash\n# Probe aggregate serialized bytes; must stay <= 33554432 (32 MiB) per method.\nurl=\"https://mcp.example.com/mcp\"; cursor=\"\"; bytes=0\nwhile :; do\n  body=$(curl -s \"$url\" -H 'content-type: application/json' \\\n    -d \"{\\\"jsonrpc\\\":\\\"2.0\\\",\\\"id\\\":1,\\\"method\\\":\\\"tools/list\\\"${cursor:+,\\\"params\\\":{\\\"cursor\\\":\\\"$cursor\\\"}}}\")\n  bytes=$((bytes + $(printf '%s' \"$body\" | jq -c '.result' | wc -c)))\n  [ \"$bytes\" -gt 33554432 ] && { echo \"would exceed 32 MiB\"; exit 1; }\n  cursor=$(printf '%s' \"$body\" | jq -r '.result.nextCursor // empty');\n  [ -z \"$cursor\" ] && break\ndone; echo \"bytes=$bytes ok\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep tool descriptions and JSON Schemas concise server-side.","Strip example payloads from catalogue entries.","Split very verbose catalogues across multiple servers."],"tags":["mcp","pagination","limits","memory"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}