ruvnet/ruflo · error

peer registry is full

Error message

peer registry is full (${MAX_PEERS})

What it means

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.

Solutions

  1. List current peers and remove stale/unused ones (e.g. via removePeer) to free a slot, then re-run addPeer.
  2. Raise MAX_PEERS if your deployment legitimately needs more peers (edit the constant and redeploy).
  3. Deduplicate before adding: check whether the nodeId already exists and skip addPeer for known peers.
  4. Audit the registry file for leaked duplicate/stale entries from failed automations and clean it.

Example fix

// before
addPeer(base, { nodeId, url, publicKey }); // throws when full
// after
const peers = readPeers(base);
if (!peers.some(p => p.nodeId === nodeId)) {
  if (peers.length >= MAX_PEERS) removePeer(base, oldestPeer.nodeId);
  addPeer(base, { nodeId, url, publicKey });
}
Defensive patterns

Strategy: try-catch

Validate before calling

const peers = readPeers(basePath);
if (peers.length >= MAX_PEERS) throw new Error('peer registry full: remove peers before adding');

Try / catch

try {
  addPeer(basePath, input);
} catch (e) {
  if (/peer registry is full/.test(e.message)) {
    removePeer(basePath, selectStalePeer().nodeId);
    addPeer(basePath, input);
  } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of ruvnet/ruflo@2602b642d9 (2026-09-15). Data as JSON: /api/errors/728dd74916b6be68. Report an issue: GitHub.

Appendix: source

Thrown at v3/@claude-flow/cli/src/mcp-tools/agentbbs-federation.ts:269

  let u: URL;
  try { u = new URL(raw); } catch { throw new Error('peer url is not a valid URL'); }
  if (u.protocol !== 'http:' && u.protocol !== 'https:') {
    throw new Error('peer url must be http or https');
  }
  if (u.username || u.password) throw new Error('peer url must not embed credentials');
  return u.origin;
}

export function addPeer(
  basePath: string,
  input: { nodeId: string; url: string; publicKey: string; label?: string },
): FederationPeer {
  if (!NODE_ID_RE.test(input.nodeId ?? '')) throw new Error('nodeId must be 16 lowercase hex chars');
  if (!HEX64_RE.test(input.publicKey ?? '')) throw new Error('publicKey must be 64 lowercase hex chars');
  const url = validatePeerUrl(String(input.url));

  const peers = readPeers(basePath);
  if (peers.length >= MAX_PEERS) throw new Error(`peer registry is full (${MAX_PEERS})`);

  const existing = peers.find(p => p.nodeId === input.nodeId);
  if (existing) {
    // Re-pinning a different key for a known nodeId is how a key-substitution
    // attack would present. Require an explicit remove first.
    if (existing.publicKey !== input.publicKey) {
      throw new Error(`nodeId ${input.nodeId} is already pinned to a different publicKey; remove it first`);
    }
    existing.url = url;
    if (input.label) existing.label = input.label;
    writePeers(basePath, peers);
    return existing;
  }

  const peer: FederationPeer = {
    nodeId: input.nodeId,
    url,
    publicKey: input.publicKey,

View on GitHub (pinned to 2602b642d9)