ruvnet/ruflo · error
fetchAgentCard: card exceeds ${maxBytes} bytes
Error message
fetchAgentCard: card exceeds ${maxBytes} bytes What it means
Anti-bloat guard in fetchAgentCard(): after the response body is read, if the text exceeds options.maxBytes (default 256 KiB, measured on the decoded string length) the card is refused before JSON parsing. This bounds memory and blocks padded or malicious card payloads.
Source
Thrown at v3/@claude-flow/plugin-agent-federation/src/a2a/consume.ts:70
const maxBytes = options.maxBytes ?? 256 * 1024;
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), options.timeoutMs ?? 10_000);
let text: string;
try {
const res = await fetchImpl(sourceUrl, {
signal: controller.signal,
headers: { accept: 'application/json' },
});
if (!res.ok) {
throw new Error(`fetchAgentCard: ${sourceUrl} returned HTTP ${res.status}`);
}
text = await res.text();
} finally {
clearTimeout(timer);
}
if (text.length > maxBytes) {
throw new Error(`fetchAgentCard: card exceeds ${maxBytes} bytes`);
}
let parsed: unknown;
try {
parsed = JSON.parse(text);
} catch {
throw new Error(`fetchAgentCard: ${sourceUrl} did not return valid JSON`);
}
const validation = validateAgentCard(parsed);
if (!validation.valid) {
throw new Error(
`fetchAgentCard: invalid A2A agent card from ${sourceUrl}: ${validation.errors.join('; ')}`,
);
}
return { card: parsed as A2AAgentCard, sourceUrl };
}
View on GitHub (pinned to fa13ee4ad6)
Solutions
- Inspect the URL manually — oversized responses often mean the wrong endpoint is being served
- Raise the cap consciously via options.maxBytes if the card is legitimately larger
- Reduce card size on the serving side (strip base64 assets, shorten metadata)
- If sizes are unpredictable, pre-flight with a HEAD request and check content-length before fetching
Example fix
// before
await fetchAgentCard(url);
// after
await fetchAgentCard(url, { maxBytes: 1024 * 1024 }); // explicit, conscious cap Defensive patterns
Strategy: validation
Validate before calling
// pre-flight size via HEAD so you never read an oversized body
const head = await fetch(cardUrl, { method: 'HEAD' });
const len = Number(head.headers.get('content-length'));
if (Number.isFinite(len) && len > MAX_BYTES) {
throw new RangeError('agent card too large before download');
}
await fetchAgentCard(base, { maxBytes: MAX_BYTES }); Try / catch
try {
await fetchAgentCard(base, opts);
} catch (e) {
if (String(e).includes('card exceeds')) {
// decide consciously: raise the cap or reject this peer
await fetchAgentCard(base, { ...opts, maxBytes: MAX_BYTES * 4 });
} else {
throw e;
}
} Prevention
- Set maxBytes explicitly instead of relying on the 256 KiB default
- Keep served cards small: no base64 assets, terse metadata
- Pre-flight with HEAD where content-length is trustworthy
- Alert on cards near the cap so growth is visible
When it happens
Trigger: A peer serving a legitimately large card (inlined base64 icons, very long descriptions/metadata arrays) past the default cap; a misconfigured server returning a huge JSON (e.g. an app bundle on the wrong route); an adversarial peer deliberately padding the card.
Common situations: Defaulting maxBytes while fetching from peers with verbose cards; gateways that append banners or wrap responses; cards that embed full capability catalogs.
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
- fetchAgentCard: ${sourceUrl} returned HTTP ${res.status}
- fetchAgentCard: ${sourceUrl} did not return valid JSON
- HTTP transport failed: ${firstError instanceof Error ? first
- Failed to fetch ${baseURL}/models: ${response.status} ${resp
- Resolved IP for ${hostname} is internal (${address})
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/ba91a44f0a90d352.
Report an issue: GitHub.