{"record":{"id":"68ad93e6dd68488b","repo":"ruvnet/ruflo","slug":"node-agentid-not-found","errorCode":null,"errorMessage":"Node ${agentId} not found","messagePattern":"Node (.+?) not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/swarm/src/topology-manager.ts","lineNumber":173,"sourceCode":"    for (const partition of this.state.partitions) {\n      partition.nodes = partition.nodes.filter(n => n !== agentId);\n      if (partition.leader === agentId) {\n        partition.leader = partition.nodes[0] || '';\n      }\n    }\n\n    this.emit('node.removed', { agentId });\n\n    // Trigger rebalance if needed\n    if (this.config.autoRebalance) {\n      await this.rebalance();\n    }\n  }\n\n  async updateNode(agentId: string, updates: Partial<TopologyNode>): Promise<void> {\n    const node = this.nodeIndex.get(agentId);\n    if (!node) {\n      throw new Error(`Node ${agentId} not found`);\n    }\n\n    // Apply updates\n    if (updates.role !== undefined) node.role = updates.role;\n    if (updates.status !== undefined) node.status = updates.status;\n    if (updates.connections !== undefined) {\n      node.connections = updates.connections;\n      this.adjacencyList.set(agentId, new Set(updates.connections));\n    }\n    if (updates.metadata !== undefined) {\n      node.metadata = { ...node.metadata, ...updates.metadata };\n    }\n\n    this.emit('node.updated', { agentId, updates });\n  }\n\n  getLeader(): string | undefined {\n    return this.state.leader;","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/swarm/src/topology-manager.ts#L155-L191","documentation":"updateNode() mutates a node looked up by agentId in nodeIndex; an unknown id throws before any field is applied. The index is keyed by the bare agentId, not by the generated node id (node_ plus agentId). Removal, including auto-rebalance evictions, deletes the entry, so updates racing a removal will miss.","triggerScenarios":"Calling updateNode(agentId, ...) for an agent never added, already removed, or using the prefixed node.id instead of the bare agentId; status pings that race removeNode during rebalance.","commonSituations":"Confusing node.id with agentId in logs or scripts; heartbeats arriving after a node was evicted; typos in scripted agent ids.","solutions":["Confirm you pass the bare agentId (not the node_-prefixed id) to updateNode","Check the node exists via getState().nodes before updating","If the node was removed, re-add it with addNode instead of updating"],"exampleFix":"// before\nawait topology.updateNode(`node_${agentId}`, { status: 'active' }); // throws: index is keyed by agentId\n\n// after\nawait topology.updateNode(agentId, { status: 'active' });","handlingStrategy":"validation","validationCode":"function findNode(topology: TopologyManager, agentId: string): TopologyNode | undefined {\n  return topology.getState().nodes.find(n => n.agentId === agentId);\n}\n\nif (!findNode(topology, agentId)) {\n  await topology.addNode(agentId, 'worker'); // node was evicted: rejoin\n}\nawait topology.updateNode(agentId, { status: 'active' });","typeGuard":"function nodeExists(topology: TopologyManager, agentId: string): boolean {\n  return topology.getState().nodes.some(n => n.agentId === agentId);\n}","tryCatchPattern":"try {\n  await topology.updateNode(agentId, updates);\n} catch (err) {\n  if (err instanceof Error && err.message.endsWith(`Node ${agentId} not found`)) {\n    await topology.addNode(agentId, 'worker');\n    return topology.updateNode(agentId, updates);\n  }\n  throw err;\n}","preventionTips":["Key external bookkeeping by bare agentId, never by the generated node.id","Heartbeat loops should treat not found as a rejoin signal, not a bug","Log both agentId and node.id in topology events to catch key confusion early"],"tags":["topology","not-found","update-node","agent-id"],"backgroundTag":"entity-not-found","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"}