ruvnet/ruflo · error
peer response exceeds size cap
Error message
peer ${peer.nodeId} response exceeds size cap What it means
syncRoomFromPeer enforces MAX_SYNC_RESPONSE_BYTES on the peer's response body before parsing. The error means the peer returned a response larger than the configured cap, so the client refuses to read/parse it to bound memory usage from malicious or misbehaving peers.
Solutions
- Sync more frequently so the incremental delta per sync stays under the size cap.
- If the peer supports query parameters, narrow the sync window (since/limit) to reduce response size.
- If the backlog is legitimately large, prune/compact envelopes on the peer or raise MAX_SYNC_RESPONSE_BYTES deliberately for that deployment (trade-off: more memory per sync).
- Investigate the peer if the size is implausible — an oversized response may indicate a misbehaving or hostile node.
Example fix
// before
await syncRoomFromPeer(peer, roomId); // huge backlog -> size cap error
// after
for (const window of [3600, 86400, 604800]) { // grow until under cap
try { await syncRoomFromPeer(peer, roomId, { sinceSeconds: window }); break; }
catch (e) { if (!/size cap/.test(e.message)) throw e; }
} Defensive patterns
Strategy: fallback
Validate before calling
// preflight: request a small window first
const probe = await fetch(syncUrl + '?since=3600');
const len = Number(probe.headers.get('content-length') ?? 0);
if (len > MAX_SYNC_RESPONSE_BYTES) console.warn('response would exceed size cap'); Type guard
function isWithinCap(text: string, cap: number): boolean { return text.length <= cap; } Try / catch
try {
await syncRoomFromPeer(peer, roomId);
} catch (e) {
if (/response exceeds size cap/.test(e.message)) {
await syncRoomFromPeer(peer, roomId, { sinceSeconds: 3600 }); // smaller delta
return;
}
throw e;
} Prevention
- Sync rooms frequently to keep deltas small
- Use since/limit query parameters to bound responses
- Flag peers that repeatedly exceed the cap as misbehaving
- Only raise the cap deliberately and with memory budgeting
When it happens
Trigger: Syncing a room whose peer has accumulated an envelope backlog exceeding MAX_SYNC_RESPONSE_BYTES, or a malicious/misconfigured peer returning an oversized (or unbounded) payload for the sync URL.
Common situations: Long-lived room with months of unmerged envelopes; peer ignoring since/limit parameters and returning everything; a compromised or buggy peer streaming an arbitrary-size response.
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
- nodeId is already pinned to a different publicKey; remove…
- peer returned
- PEER_UNKNOWN
- PRIVATE_ADDRESS
- Resolved IP for is internal ( )
AI-assisted analysis of ruvnet/ruflo@2602b642d9 (2026-09-15).
Data as JSON: /api/errors/f555ab5144cc1cc9.
Report an issue: GitHub.
Appendix: source
Thrown at v3/@claude-flow/cli/src/mcp-tools/agentbbs-federation.ts:394
/** Pull one room from one peer and merge what verifies. */
export async function syncRoomFromPeer(
basePath: string,
peer: FederationPeer,
roomId: string,
fetchImpl: typeof fetch = fetch,
): Promise<MergeResult & { peerNodeId: string; roomId: string }> {
validateRoomId(roomId);
const since = peer.lastSeq?.[roomId] ?? 0;
const url = `${peer.url}/agentbbs/v1/rooms/${encodeURIComponent(roomId)}/envelopes?since=${since}`;
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), SYNC_TIMEOUT_MS);
let body: any;
try {
const res = await fetchImpl(url, { signal: controller.signal, headers: { accept: 'application/json' } });
if (!res.ok) throw new Error(`peer ${peer.nodeId} returned ${res.status}`);
const text = await res.text();
if (text.length > MAX_SYNC_RESPONSE_BYTES) throw new Error(`peer ${peer.nodeId} response exceeds size cap`);
body = JSON.parse(text);
} finally {
clearTimeout(timer);
}
const envelopes: SignedEnvelope[] = Array.isArray(body?.envelopes) ? body.envelopes : [];
const merged = await mergeEnvelopes(basePath, roomId, envelopes, peer.publicKey);
const peers = readPeers(basePath);
const rec = peers.find(p => p.nodeId === peer.nodeId);
if (rec) {
rec.lastSyncedAt = new Date().toISOString();
rec.lastSeq = rec.lastSeq ?? {};
const maxSeq = envelopes.reduce((m, e) => Math.max(m, Number(e.seq) || 0), since);
rec.lastSeq[roomId] = maxSeq;
writePeers(basePath, peers);
}
return { ...merged, peerNodeId: peer.nodeId, roomId };View on GitHub (pinned to 2602b642d9)