{"record":{"id":"56f754a1ce48704c","repo":"cilium/cilium","slug":"failed-while-updating-peer-v-v-with-asn-v-w","errorCode":null,"errorMessage":"failed while updating peer %v:%v with ASN %v: %w","messagePattern":"failed while updating peer (.+?):(.+?) with ASN (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/bgp/gobgp/peer.go","lineNumber":46,"sourceCode":"// UpdateNeighbor will update the existing CiliumBGPNeighbor in the gobgp.BgpServer.\nfunc (g *GoBGPServer) UpdateNeighbor(ctx context.Context, n *types.Neighbor) error {\n\toldPeer, err := g.getExistingPeer(ctx, n.Address, n.ASN)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get existing peer: %w\", err)\n\t}\n\n\tnewPeer := ToGoBGPPeer(n, oldPeer, n.Address.Is4())\n\n\tneedsHardReset := g.needsHardReset(oldPeer, newPeer)\n\n\t// update peer config\n\tpeerReq := &gobgp.UpdatePeerRequest{\n\t\tPeer: ToGoBGPPeer(n, oldPeer, n.Address.Is4()),\n\t}\n\n\tupdateRes, err := g.server.UpdatePeer(ctx, peerReq)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed while updating peer %v:%v with ASN %v: %w\", oldPeer.Conf.NeighborAddress, oldPeer.Transport.RemotePort, oldPeer.Conf.PeerAsn, err)\n\t}\n\n\t// perform full / soft peer reset if necessary\n\tif needsHardReset || updateRes.NeedsSoftResetIn {\n\t\tresetReq := &gobgp.ResetPeerRequest{\n\t\t\tAddress:       oldPeer.Conf.NeighborAddress,\n\t\t\tCommunication: \"Peer configuration changed\",\n\t\t}\n\t\tif !needsHardReset {\n\t\t\tresetReq.Soft = true\n\t\t\tresetReq.Direction = gobgp.ResetPeerRequest_DIRECTION_IN\n\t\t}\n\t\tif err = g.server.ResetPeer(ctx, resetReq); err != nil {\n\t\t\treturn fmt.Errorf(\"failed while resetting peer %v:%v in ASN %v: %w\", oldPeer.Conf.NeighborAddress, oldPeer.Transport.RemotePort, oldPeer.Conf.PeerAsn, err)\n\t\t}\n\t}\n\n\treturn nil","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/cilium/cilium/blob/ac7b90affa4baf0642e6685319d56907b3a73a6d/pkg/bgp/gobgp/peer.go#L28-L64","documentation":"UpdateNeighbor wraps errors from the gobgp UpdatePeer gRPC call. The message includes the OLD peer's address:port and ASN (from oldPeer.Conf), so the wrapped gobgp error is the real cause — commonly the peer was concurrently removed or the update conflicts with server state.","triggerScenarios":"Calling UpdateNeighbor when g.server.UpdatePeer rejects the request — e.g. no peer with that address exists anymore (removed concurrently), invalid peer configuration produced by ToGoBGPPeer, or a gRPC/transport failure.","commonSituations":"Race between reconciliation deleting and updating the same neighbor; changing fields gobgp disallows updating in place; ASN/port fields of oldPeer zero-valued because the old lookup returned an unexpected peer; control-plane restarting mid-update.","solutions":["Inspect the wrapped %w error from gobgp for the precise rejection reason","Re-check that the peer still exists before updating; if it was removed, Add it again","Avoid changing immutable peer fields in place — delete and re-add the neighbor instead","Retry the update if the failure was a transient gRPC error","Validate that getExistingPeer returned the intended peer (check address/ASN in the message)"],"exampleFix":"// before\nerr := server.UpdateNeighbor(ctx, n) // peer removed concurrently\n// after\nif _, err := server.getExistingPeer(ctx, n.Address, n.ASN); err != nil {\n    err = server.AddNeighbor(ctx, n)\n} else {\n    err = server.UpdateNeighbor(ctx, n)\n}","handlingStrategy":"try-catch","validationCode":"if _, err := server.getExistingPeer(ctx, n.Address, n.ASN); err != nil {\n    return fmt.Errorf(\"cannot update non-existent peer: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"updateRes, err := g.server.UpdatePeer(ctx, peerReq)\nif err != nil {\n    if status.Code(err) == codes.NotFound {\n        return g.AddNeighbor(ctx, n)\n    }\n    return fmt.Errorf(\"failed while updating peer %v:%v with ASN %v: %w\", ...)\n}","preventionTips":["Treat codes.NotFound as re-add, not fatal","Avoid mutating immutable peer fields in place; delete+re-add instead","Serialize reconciles per neighbor to avoid delete/update races","Verify oldPeer returned by getExistingPeer matches the intended neighbor"],"tags":["bgp","grpc","peer-config","race-condition"],"backgroundTag":"bgp-peer-update-failed","analyzedSha":"ac7b90affa4baf0642e6685319d56907b3a73a6d","analyzedAt":"2026-08-31T18:27:15.868Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}