Hmbown/CodeWhale · error

MCP exceeded the -byte aggregate catalog limit

Error message

MCP {} exceeded the {}-byte aggregate catalog limit

What it means

observe_page accumulates the serialized size in bytes of every page received. When the aggregate exceeds max_bytes the listing fails rather than returning partial results, protecting memory and context budgets from oversized server catalogs.

Solutions

  1. Increase the max_bytes aggregate budget
  2. Trim descriptions/metadata exposed by the MCP server
  3. Reduce items per page via server-side filtering

Example fix

// before
max_bytes: 256 * 1024
// after
max_bytes: 1024 * 1024
Defensive patterns

Strategy: try-catch

Validate before calling

// estimate payload: items x avg entry bytes
let est_bytes = expected_items * avg_entry_bytes;
assert!(max_bytes > est_bytes, "max_bytes below expected payload");

Try / catch

match client.list_resources_with_metadata().await {
    Ok(entries) => use(entries),
    Err(e) if e.to_string().contains("-byte aggregate catalog limit") => {
        eprintln!("catalog payload exceeds byte budget: {}", e);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: list_paginated's running byte counter (self.bytes) exceeds max_bytes after recording a page, typically with large entries (long descriptions, embedded content) even at modest page counts.

Common situations: MCP server with verbose resource descriptions or huge tool schemas; max_bytes tuned too low; a server echoing bloated metadata.

Understand the failure class

Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/6eaac74fb558f7b7. Report an issue: GitHub.

Appendix: source

Thrown at crates/mcp/src/stdio_client.rs:383

        self.pages = self.pages.saturating_add(1);
        self.items = self.items.saturating_add(values.len());
        self.bytes = self.bytes.saturating_add(serde_json::to_vec(page)?.len());
        if self.pages > self.max_pages {
            bail!(
                "MCP {} exceeded the {}-page catalog limit",
                self.method,
                self.max_pages
            );
        }
        if self.items > self.max_items {
            bail!(
                "MCP {} exceeded the {}-item catalog limit",
                self.method,
                self.max_items
            );
        }
        if self.bytes > self.max_bytes {
            bail!(
                "MCP {} exceeded the {}-byte aggregate catalog limit",
                self.method,
                self.max_bytes
            );
        }

        let next_cursor = match page.get("nextCursor") {
            None => None,
            Some(Value::String(cursor)) => Some(cursor.clone()),
            Some(_) => bail!("MCP {} returned a non-string nextCursor", self.method),
        };
        if let Some(cursor) = next_cursor.as_ref()
            && !self.seen_cursors.insert(cursor.clone())
        {
            bail!("MCP {} repeated a pagination cursor", self.method);
        }
        if next_cursor.is_some() && self.pages >= self.max_pages {
            bail!(

View on GitHub (pinned to 73e0f67d83)