{"record":{"id":"ef19287e4d241d45","repo":"ruvnet/ruflo","slug":"peer-unknown","errorCode":"PEER_UNKNOWN","errorMessage":"PEER_UNKNOWN: ${targetNodeId}","messagePattern":"PEER_UNKNOWN: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/plugin-agent-federation/src/plugin.ts","lineNumber":373,"sourceCode":"      sendToNode: async (targetNodeId, envelope) => {\n        // ADR-104: real wire send via the loaded transport. If the\n        // transport failed to load OR the peer's address can't be\n        // resolved, log + return (the upstream RoutingService.send\n        // already wraps this in try/catch and returns a RoutingResult\n        // with the error to the caller).\n        if (!transport) {\n          context.logger.debug(\n            `Federation send (in-process noop): ${envelope.envelopeId} → ${targetNodeId}`,\n          );\n          return;\n        }\n        const address = resolveAddress(targetNodeId);\n        const peer = discovery.getPeer(targetNodeId);\n        if (!address || !peer) {\n          context.logger.warn(\n            `Federation send aborted: peer ${targetNodeId} not in discovery registry`,\n          );\n          throw new Error(`PEER_UNKNOWN: ${targetNodeId}`);\n        }\n        const signatureVersion = selectEnvelopeSignatureVersion(\n          signatureMode,\n          peer.capabilities.supportedProtocols,\n          envelope.messageType,\n        );\n        // Build the AgentMessage WITHOUT signature first, canonicalize\n        // the bytes, sign them, then attach the signature to metadata.\n        // The receiver runs the same canonicalization and verifies\n        // against this node's published public key.\n        const baseMessage: AgentMessage = {\n          id: envelope.envelopeId,\n          type: envelope.messageType,\n          payload: envelope as unknown,\n          metadata: {\n            sourceNodeId: envelope.sourceNodeId,\n            targetNodeId: envelope.targetNodeId,\n            sessionId: envelope.sessionId,","sourceCodeStart":355,"sourceCodeEnd":391,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/plugin-agent-federation/src/plugin.ts#L355-L391","documentation":"Raised when the federation layer attempts delivery of an envelope over a real transport but the target cannot be resolved: resolveAddress(targetNodeId) returns no address or discovery.getPeer() has no registry entry for the node. Note the contrast: with no transport configured the send is silently dropped as an in-process noop; PEER_UNKNOWN means routing was attempted and discovery does not know the peer.","triggerScenarios":"Sending to a nodeId that never appeared via discovery, a peer that disconnected and was evicted from the registry, a node missing from staticPeers, or a mistyped target ID — while a transport is configured.","commonSituations":"Race where the remote node just joined and discovery has not propagated yet; the peer process crashed and its entry expired; clusters split across environments or mismatched staticPeers lists.","solutions":["Verify the exact targetNodeId against the discovery registry (peer list/status tooling)","Ensure the peer node is online and re-advertised itself (federation_init plus discovery), or add it to staticPeers","If the peer just joined, retry after a short backoff to allow discovery propagation"],"exampleFix":"// before\nawait client.callTool('federation_send', { targetNodeId: 'node-b', envelope }); // PEER_UNKNOWN: node-b\n\n// after\nconst peers = await client.callTool('federation_peers', {});\nif (!peerIds(peers).includes('node-b')) {\n  await waitForDiscovery('node-b'); // or add node-b to staticPeers\n}\nawait client.callTool('federation_send', { targetNodeId: 'node-b', envelope });","handlingStrategy":"try-catch","validationCode":"const known = new Set<string>();\nsubscribeToDiscoveryUpdates(\n  (peer) => known.add(peer.nodeId),\n  (peer) => known.delete(peer.nodeId),\n);\nif (!known.has(targetNodeId)) {\n  throw new Error(`refusing send: ${targetNodeId} not in known peers; refresh discovery first`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await federationSend(envelope, targetNodeId);\n} catch (e) {\n  if (e instanceof Error && /^PEER_UNKNOWN: /.test(e.message)) {\n    const nodeId = e.message.slice('PEER_UNKNOWN: '.length);\n    await refreshDiscovery();\n    if (!isPeerKnown(nodeId)) deadLetter(envelope, nodeId); // do not blindly retry\n  } else throw e;\n}","preventionTips":["Wait for a discovery event confirming a peer before the first send","Keep staticPeers aligned with actual cluster membership","Treat PEER_UNKNOWN as discovery lag or churn, not as a transient network blip to retry blindly"],"tags":["federation","peer-discovery","p2p","network","routing"],"backgroundTag":"unknown-peer","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}