{"record":{"id":"728dd74916b6be68","repo":"ruvnet/ruflo","slug":"peer-registry-is-full-max-peers","errorCode":null,"errorMessage":"peer registry is full (${MAX_PEERS})","messagePattern":"peer registry is full \\((.+?)\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/mcp-tools/agentbbs-federation.ts","lineNumber":269,"sourceCode":"  let u: URL;\n  try { u = new URL(raw); } catch { throw new Error('peer url is not a valid URL'); }\n  if (u.protocol !== 'http:' && u.protocol !== 'https:') {\n    throw new Error('peer url must be http or https');\n  }\n  if (u.username || u.password) throw new Error('peer url must not embed credentials');\n  return u.origin;\n}\n\nexport function addPeer(\n  basePath: string,\n  input: { nodeId: string; url: string; publicKey: string; label?: string },\n): FederationPeer {\n  if (!NODE_ID_RE.test(input.nodeId ?? '')) throw new Error('nodeId must be 16 lowercase hex chars');\n  if (!HEX64_RE.test(input.publicKey ?? '')) throw new Error('publicKey must be 64 lowercase hex chars');\n  const url = validatePeerUrl(String(input.url));\n\n  const peers = readPeers(basePath);\n  if (peers.length >= MAX_PEERS) throw new Error(`peer registry is full (${MAX_PEERS})`);\n\n  const existing = peers.find(p => p.nodeId === input.nodeId);\n  if (existing) {\n    // Re-pinning a different key for a known nodeId is how a key-substitution\n    // attack would present. Require an explicit remove first.\n    if (existing.publicKey !== input.publicKey) {\n      throw new Error(`nodeId ${input.nodeId} is already pinned to a different publicKey; remove it first`);\n    }\n    existing.url = url;\n    if (input.label) existing.label = input.label;\n    writePeers(basePath, peers);\n    return existing;\n  }\n\n  const peer: FederationPeer = {\n    nodeId: input.nodeId,\n    url,\n    publicKey: input.publicKey,","sourceCodeStart":251,"sourceCodeEnd":287,"githubUrl":"https://github.com/ruvnet/ruflo/blob/2602b642d92234c710ffbe96bfb33007d481ceab/v3/@claude-flow/cli/src/mcp-tools/agentbbs-federation.ts#L251-L287","documentation":"addPeer() enforces a maximum peer count (MAX_PEERS) on the federation peer registry file to bound file size and sync cost. When the registry already holds MAX_PEERS entries, adding another is refused. Removing an existing peer first is required to free a slot.","triggerScenarios":"Calling addPeer() when readPeers(basePath) returns peers.length >= MAX_PEERS — i.e. every slot in peers.json is occupied and one more peer is requested.","commonSituations":"Long-running federation clusters that accumulated peers over time; automated tooling re-adding peers on each deploy without deduplication; leaked/stale entries from decommissioned nodes never removed.","solutions":["List current peers and remove stale/unused ones (e.g. via removePeer) to free a slot, then re-run addPeer.","Raise MAX_PEERS if your deployment legitimately needs more peers (edit the constant and redeploy).","Deduplicate before adding: check whether the nodeId already exists and skip addPeer for known peers.","Audit the registry file for leaked duplicate/stale entries from failed automations and clean it."],"exampleFix":"// before\naddPeer(base, { nodeId, url, publicKey }); // throws when full\n// after\nconst peers = readPeers(base);\nif (!peers.some(p => p.nodeId === nodeId)) {\n  if (peers.length >= MAX_PEERS) removePeer(base, oldestPeer.nodeId);\n  addPeer(base, { nodeId, url, publicKey });\n}","handlingStrategy":"try-catch","validationCode":"const peers = readPeers(basePath);\nif (peers.length >= MAX_PEERS) throw new Error('peer registry full: remove peers before adding');","typeGuard":null,"tryCatchPattern":"try {\n  addPeer(basePath, input);\n} catch (e) {\n  if (/peer registry is full/.test(e.message)) {\n    removePeer(basePath, selectStalePeer().nodeId);\n    addPeer(basePath, input);\n  } else throw e;\n}","preventionTips":["Track registry size and alert before hitting MAX_PEERS","Remove peer entries during node decommissioning","Idempotently skip addPeer for already-known nodeIds","Avoid re-adding all peers on every deploy"],"tags":["capacity-limit","registry-full","federation","resource-limit"],"backgroundTag":"value-out-of-range","analyzedSha":"2602b642d92234c710ffbe96bfb33007d481ceab","analyzedAt":"2026-09-15T22:58:14.805Z","contentChangedAt":"2026-09-15T22:58:14.805Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}