cilium/cilium · error
failed adding policy %s: %w
Error message
failed adding policy %s: %w
What it means
After defined sets are added, AddRoutePolicy registers the policy itself via the server's AddPolicy. On failure it rolls back the created defined sets and wraps the error with the policy name. The policy was rejected by GoBGP - typically because a policy with the same name exists or the policy references statements/sets gobgp considers invalid.
Source
Thrown at pkg/bgp/gobgp/server.go:291
// AddRoutePolicy adds a new routing policy into the global policies of the server.
func (g *GoBGPServer) AddRoutePolicy(ctx context.Context, r types.RoutePolicyRequest) error {
if r.Policy == nil {
return fmt.Errorf("nil policy in the RoutePolicyRequest")
}
policy, definedSets := toGoBGPPolicy(r.Policy)
for i, ds := range definedSets {
err := g.server.AddDefinedSet(ctx, &gobgp.AddDefinedSetRequest{DefinedSet: ds})
if err != nil {
g.deleteDefinedSets(ctx, definedSets[:i]) // clean up already created defined sets
return fmt.Errorf("failed adding policy defined set %s: %w", ds.Name, err)
}
}
err := g.server.AddPolicy(ctx, &gobgp.AddPolicyRequest{Policy: policy})
if err != nil {
g.deleteDefinedSets(ctx, definedSets) // clean up defined sets
return fmt.Errorf("failed adding policy %s: %w", policy.Name, err)
}
// Note that we are using global policy assignment here (per-neighbor policies work only in the route-server mode)
assignment := g.getGlobalPolicyAssignment(policy, r.Policy.Type, r.DefaultExportAction)
err = g.server.AddPolicyAssignment(ctx, &gobgp.AddPolicyAssignmentRequest{Assignment: assignment})
if err != nil {
g.deletePolicy(ctx, policy) // clean up policy
g.deleteDefinedSets(ctx, definedSets) // clean up defined sets
return fmt.Errorf("failed adding policy assignment %s: %w", assignment.Name, err)
}
return nil
}
// RemoveRoutePolicy removes a routing policy from the global policies of the server.
func (g *GoBGPServer) RemoveRoutePolicy(ctx context.Context, r types.RoutePolicyRequest) error {
if r.Policy == nil {
return fmt.Errorf("nil policy in the RoutePolicyRequest")View on GitHub (pinned to ac7b90affa)
Solutions
- Read the wrapped error for the exact gobgp rejection (AlreadyExists vs validation)
- Make reconciliation idempotent: remove or diff the existing policy before AddRoutePolicy
- Check the policy name for collisions across multiple CiliumBGPPolicy objects
- Validate statement structure (match conditions, actions, default export action) before applying
Example fix
// before
err := bgpServer.AddRoutePolicy(ctx, req) // fails: policy already exists
// after
if err := bgpServer.RemoveRoutePolicy(ctx, req); err != nil && !errors.Is(err, ErrPolicyNotFound) {
return err
}
err := bgpServer.AddRoutePolicy(ctx, req) Defensive patterns
Strategy: validation
Validate before calling
if req.Policy == nil || req.Policy.Name == "" { return fmt.Errorf("policy needs a name") }
for _, s := range req.Policy.Statements {
if len(s.MatchPrefixes) == 0 && len(s.MatchNeighbors) == 0 { return fmt.Errorf("statement has no match clauses") }
}
err := srv.AddRoutePolicy(ctx, req) Type guard
func namedPolicy(r types.RoutePolicyRequest) bool { return r.Policy != nil && r.Policy.Name != "" } Try / catch
err := srv.AddRoutePolicy(ctx, req)
if err != nil && strings.Contains(err.Error(), "failed adding policy") {
// policy name likely already exists: replace idempotently
_ = srv.RemoveRoutePolicy(ctx, req)
err = srv.AddRoutePolicy(ctx, req)
} Prevention
- Treat AddRoutePolicy as non-idempotent: remove or diff before add
- Give each CiliumBGPPolicy a unique, deterministic name
- Clean up leftover policies after crashed reconciliations
- Validate statement match/action structure before applying
When it happens
Trigger: AddRoutePolicy with a policy whose name collides with an existing one, or whose statements (match clauses/actions) fail gobgp validation after the defined sets were accepted.
Common situations: Re-applying an unchanged policy on every reconcile (name already exists); malformed match/route-action combos in the CRD; leftover policy state from a previous crashed reconciliation.
Related errors
- failed adding policy defined set %s: %w
- failed adding policy assignment %s: %w
- nil policy in the RoutePolicyRequest
- failed to add %s policy: %w
- failed configuring BGP server's global import policy: %w
AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31).
Data as JSON: /api/errors/999eb009b6ed46ff.
Report an issue: GitHub.