{"record":{"id":"ba91a44f0a90d352","repo":"ruvnet/ruflo","slug":"fetchagentcard-card-exceeds-maxbytes-bytes","errorCode":null,"errorMessage":"fetchAgentCard: card exceeds ${maxBytes} bytes","messagePattern":"fetchAgentCard: card exceeds (.+?) bytes","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/plugin-agent-federation/src/a2a/consume.ts","lineNumber":70,"sourceCode":"  const maxBytes = options.maxBytes ?? 256 * 1024;\n\n  const controller = new AbortController();\n  const timer = setTimeout(() => controller.abort(), options.timeoutMs ?? 10_000);\n  let text: string;\n  try {\n    const res = await fetchImpl(sourceUrl, {\n      signal: controller.signal,\n      headers: { accept: 'application/json' },\n    });\n    if (!res.ok) {\n      throw new Error(`fetchAgentCard: ${sourceUrl} returned HTTP ${res.status}`);\n    }\n    text = await res.text();\n  } finally {\n    clearTimeout(timer);\n  }\n  if (text.length > maxBytes) {\n    throw new Error(`fetchAgentCard: card exceeds ${maxBytes} bytes`);\n  }\n\n  let parsed: unknown;\n  try {\n    parsed = JSON.parse(text);\n  } catch {\n    throw new Error(`fetchAgentCard: ${sourceUrl} did not return valid JSON`);\n  }\n\n  const validation = validateAgentCard(parsed);\n  if (!validation.valid) {\n    throw new Error(\n      `fetchAgentCard: invalid A2A agent card from ${sourceUrl}: ${validation.errors.join('; ')}`,\n    );\n  }\n  return { card: parsed as A2AAgentCard, sourceUrl };\n}\n","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/plugin-agent-federation/src/a2a/consume.ts#L52-L88","documentation":"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.","triggerScenarios":"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.","commonSituations":"Defaulting maxBytes while fetching from peers with verbose cards; gateways that append banners or wrap responses; cards that embed full capability catalogs.","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"],"exampleFix":"// before\nawait fetchAgentCard(url);\n// after\nawait fetchAgentCard(url, { maxBytes: 1024 * 1024 }); // explicit, conscious cap","handlingStrategy":"validation","validationCode":"// pre-flight size via HEAD so you never read an oversized body\nconst head = await fetch(cardUrl, { method: 'HEAD' });\nconst len = Number(head.headers.get('content-length'));\nif (Number.isFinite(len) && len > MAX_BYTES) {\n  throw new RangeError('agent card too large before download');\n}\nawait fetchAgentCard(base, { maxBytes: MAX_BYTES });","typeGuard":null,"tryCatchPattern":"try {\n  await fetchAgentCard(base, opts);\n} catch (e) {\n  if (String(e).includes('card exceeds')) {\n    // decide consciously: raise the cap or reject this peer\n    await fetchAgentCard(base, { ...opts, maxBytes: MAX_BYTES * 4 });\n  } else {\n    throw e;\n  }\n}","preventionTips":["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"],"tags":["size-limit","network","a2a"],"backgroundTag":"payload-too-large","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}