cilium/cilium · error
failed while updating peer %v:%v with ASN %v: %w
Error message
failed while updating peer %v:%v with ASN %v: %w
What it means
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.
Source
Thrown at pkg/bgp/gobgp/peer.go:46
// UpdateNeighbor will update the existing CiliumBGPNeighbor in the gobgp.BgpServer.
func (g *GoBGPServer) UpdateNeighbor(ctx context.Context, n *types.Neighbor) error {
oldPeer, err := g.getExistingPeer(ctx, n.Address, n.ASN)
if err != nil {
return fmt.Errorf("failed to get existing peer: %w", err)
}
newPeer := ToGoBGPPeer(n, oldPeer, n.Address.Is4())
needsHardReset := g.needsHardReset(oldPeer, newPeer)
// update peer config
peerReq := &gobgp.UpdatePeerRequest{
Peer: ToGoBGPPeer(n, oldPeer, n.Address.Is4()),
}
updateRes, err := g.server.UpdatePeer(ctx, peerReq)
if err != nil {
return fmt.Errorf("failed while updating peer %v:%v with ASN %v: %w", oldPeer.Conf.NeighborAddress, oldPeer.Transport.RemotePort, oldPeer.Conf.PeerAsn, err)
}
// perform full / soft peer reset if necessary
if needsHardReset || updateRes.NeedsSoftResetIn {
resetReq := &gobgp.ResetPeerRequest{
Address: oldPeer.Conf.NeighborAddress,
Communication: "Peer configuration changed",
}
if !needsHardReset {
resetReq.Soft = true
resetReq.Direction = gobgp.ResetPeerRequest_DIRECTION_IN
}
if err = g.server.ResetPeer(ctx, resetReq); err != nil {
return fmt.Errorf("failed while resetting peer %v:%v in ASN %v: %w", oldPeer.Conf.NeighborAddress, oldPeer.Transport.RemotePort, oldPeer.Conf.PeerAsn, err)
}
}
return nilView on GitHub (pinned to ac7b90affa)
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)
Example fix
// before
err := server.UpdateNeighbor(ctx, n) // peer removed concurrently
// after
if _, err := server.getExistingPeer(ctx, n.Address, n.ASN); err != nil {
err = server.AddNeighbor(ctx, n)
} else {
err = server.UpdateNeighbor(ctx, n)
} Defensive patterns
Strategy: try-catch
Validate before calling
if _, err := server.getExistingPeer(ctx, n.Address, n.ASN); err != nil {
return fmt.Errorf("cannot update non-existent peer: %w", err)
} Try / catch
updateRes, err := g.server.UpdatePeer(ctx, peerReq)
if err != nil {
if status.Code(err) == codes.NotFound {
return g.AddNeighbor(ctx, n)
}
return fmt.Errorf("failed while updating peer %v:%v with ASN %v: %w", ...)
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- failed while adding peer %s with ASN %d: %w
- failed to get existing peer: %w
- failed to allocate override router ID %s for node %s: %w
- failed while resetting peer %v:%v in ASN %v: %w
- listing peers failed: %w
AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31).
Data as JSON: /api/errors/56f754a1ce48704c.
Report an issue: GitHub.