{"record":{"id":"999eb009b6ed46ff","repo":"cilium/cilium","slug":"failed-adding-policy-s-w","errorCode":null,"errorMessage":"failed adding policy %s: %w","messagePattern":"failed adding policy (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/bgp/gobgp/server.go","lineNumber":291,"sourceCode":"// AddRoutePolicy adds a new routing policy into the global policies of the server.\nfunc (g *GoBGPServer) AddRoutePolicy(ctx context.Context, r types.RoutePolicyRequest) error {\n\tif r.Policy == nil {\n\t\treturn fmt.Errorf(\"nil policy in the RoutePolicyRequest\")\n\t}\n\tpolicy, definedSets := toGoBGPPolicy(r.Policy)\n\n\tfor i, ds := range definedSets {\n\t\terr := g.server.AddDefinedSet(ctx, &gobgp.AddDefinedSetRequest{DefinedSet: ds})\n\t\tif err != nil {\n\t\t\tg.deleteDefinedSets(ctx, definedSets[:i]) // clean up already created defined sets\n\t\t\treturn fmt.Errorf(\"failed adding policy defined set %s: %w\", ds.Name, err)\n\t\t}\n\t}\n\n\terr := g.server.AddPolicy(ctx, &gobgp.AddPolicyRequest{Policy: policy})\n\tif err != nil {\n\t\tg.deleteDefinedSets(ctx, definedSets) // clean up defined sets\n\t\treturn fmt.Errorf(\"failed adding policy %s: %w\", policy.Name, err)\n\t}\n\n\t// Note that we are using global policy assignment here (per-neighbor policies work only in the route-server mode)\n\tassignment := g.getGlobalPolicyAssignment(policy, r.Policy.Type, r.DefaultExportAction)\n\terr = g.server.AddPolicyAssignment(ctx, &gobgp.AddPolicyAssignmentRequest{Assignment: assignment})\n\tif err != nil {\n\t\tg.deletePolicy(ctx, policy)           // clean up policy\n\t\tg.deleteDefinedSets(ctx, definedSets) // clean up defined sets\n\t\treturn fmt.Errorf(\"failed adding policy assignment %s: %w\", assignment.Name, err)\n\t}\n\n\treturn nil\n}\n\n// RemoveRoutePolicy removes a routing policy from the global policies of the server.\nfunc (g *GoBGPServer) RemoveRoutePolicy(ctx context.Context, r types.RoutePolicyRequest) error {\n\tif r.Policy == nil {\n\t\treturn fmt.Errorf(\"nil policy in the RoutePolicyRequest\")","sourceCodeStart":273,"sourceCodeEnd":309,"githubUrl":"https://github.com/cilium/cilium/blob/ac7b90affa4baf0642e6685319d56907b3a73a6d/pkg/bgp/gobgp/server.go#L273-L309","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nerr := bgpServer.AddRoutePolicy(ctx, req) // fails: policy already exists\n// after\nif err := bgpServer.RemoveRoutePolicy(ctx, req); err != nil && !errors.Is(err, ErrPolicyNotFound) {\n    return err\n}\nerr := bgpServer.AddRoutePolicy(ctx, req)","handlingStrategy":"validation","validationCode":"if req.Policy == nil || req.Policy.Name == \"\" { return fmt.Errorf(\"policy needs a name\") }\nfor _, s := range req.Policy.Statements {\n    if len(s.MatchPrefixes) == 0 && len(s.MatchNeighbors) == 0 { return fmt.Errorf(\"statement has no match clauses\") }\n}\nerr := srv.AddRoutePolicy(ctx, req)","typeGuard":"func namedPolicy(r types.RoutePolicyRequest) bool { return r.Policy != nil && r.Policy.Name != \"\" }","tryCatchPattern":"err := srv.AddRoutePolicy(ctx, req)\nif err != nil && strings.Contains(err.Error(), \"failed adding policy\") {\n    // policy name likely already exists: replace idempotently\n    _ = srv.RemoveRoutePolicy(ctx, req)\n    err = srv.AddRoutePolicy(ctx, req)\n}","preventionTips":["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"],"tags":["go","bgp","gobgp","policy","idempotency","routing-policy"],"backgroundTag":"bgp-policy-add-rejected","analyzedSha":"ac7b90affa4baf0642e6685319d56907b3a73a6d","analyzedAt":"2026-08-31T18:27:15.868Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}