{"record":{"id":"894e8048b4f77c45","repo":"kubernetes/kops","slug":"error-creating-security-group-rule-v-v","errorCode":null,"errorMessage":"error creating security group rule %v: %v","messagePattern":"error creating security group rule (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/openstack/security_group.go","lineNumber":121,"sourceCode":"\t\treturn rules, err\n\t} else if done {\n\t\treturn rules, nil\n\t} else {\n\t\treturn rules, wait.ErrWaitTimeout\n\t}\n}\n\nfunc (c *openstackCloud) CreateSecurityGroupRule(opt sgr.CreateOptsBuilder) (*sgr.SecGroupRule, error) {\n\treturn createSecurityGroupRule(c, opt)\n}\n\nfunc createSecurityGroupRule(c OpenstackCloud, opt sgr.CreateOptsBuilder) (*sgr.SecGroupRule, error) {\n\tvar rule *sgr.SecGroupRule\n\n\tdone, err := vfs.RetryWithBackoff(writeBackoff, func() (bool, error) {\n\t\tr, err := sgr.Create(context.TODO(), c.NetworkingClient(), opt).Extract()\n\t\tif err != nil {\n\t\t\treturn false, fmt.Errorf(\"error creating security group rule %v: %v\", opt, err)\n\t\t}\n\t\trule = r\n\t\treturn true, nil\n\t})\n\tif err != nil {\n\t\treturn rule, err\n\t} else if done {\n\t\treturn rule, nil\n\t} else {\n\t\treturn rule, wait.ErrWaitTimeout\n\t}\n}\n\nfunc (c *openstackCloud) DeleteSecurityGroup(sgID string) error {\n\treturn deleteSecurityGroup(c, sgID)\n}\n\nfunc deleteSecurityGroup(c OpenstackCloud, sgID string) error {","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/openstack/security_group.go#L103-L139","documentation":"This error is returned by createSecurityGroupRule when the Neutron security-group-rule Create API call returns an error inside the writeBackoff retry loop. It wraps the gophercloud error together with the CreateOptsBuilder, so the failing rule parameters (direction, protocol, port range, remote group/CIDR) are included in the message. Common underlying causes are 409 conflicts (duplicate rule) and 400 validation errors.","triggerScenarios":"sgr.Create(context.TODO(), c.NetworkingClient(), opt).Extract() fails: the identical rule already exists (HTTP 409), invalid port range (e.g. port_range_max < min), invalid protocol, quota exceeded for security group rules, or a non-existent remote security group/CIDR is referenced.","commonSituations":"Repeated kops apply runs colliding with previously created identical rules (409 duplicate), cluster spec with invalid port ranges, project hitting Neutron quota limits, or referencing a deleted security group as the remote group.","solutions":["Read the wrapped HTTP status: on 409 the rule already exists — treat as success or delete the duplicate first","Validate the CreateOpts (port_range_min <= port_range_max, valid protocol, existing remote group ID) before calling","Check rule quota with `openstack quota show` and raise limits if exceeded","Re-apply after fixing; writeBackoff retries transient failures already"],"exampleFix":"// before: blindly create and fail on duplicates\nr, err := sgr.Create(context.TODO(), c.NetworkingClient(), opt).Extract()\n// after: tolerate already-existing rule\nr, err := sgr.Create(context.TODO(), c.NetworkingClient(), opt).Extract()\nif err != nil {\n\tif _, ok := err.(gophercloud.ErrDefault409); ok {\n\t\treturn true, nil // rule already exists\n\t}\n\treturn false, fmt.Errorf(\"error creating security group rule %v: %v\", opt, err)\n}","handlingStrategy":"validation","validationCode":"func validateRuleOpts(opt sgr.CreateOpts) error {\n\tif opt.PortRangeMin > opt.PortRangeMax {\n\t\treturn fmt.Errorf(\"port_range_min %d > port_range_max %d\", opt.PortRangeMin, opt.PortRangeMax)\n\t}\n\tif opt.Protocol != \"tcp\" && opt.Protocol != \"udp\" && opt.Protocol != \"icmp\" {\n\t\treturn fmt.Errorf(\"invalid protocol %q\", opt.Protocol)\n\t}\n\tif opt.RemoteGroupID == \"\" && opt.RemoteIPPrefix == \"\" {\n\t\treturn fmt.Errorf(\"rule needs RemoteGroupID or RemoteIPPrefix\")\n\t}\n\treturn nil\n}","typeGuard":"func isDuplicateRuleErr(err error) bool {\n\tvar conflict gophercloud.ErrDefault409\n\treturn errors.As(err, &conflict)\n}","tryCatchPattern":"rule, err := createSecurityGroupRule(c, opt)\nif err != nil {\n\tif isDuplicateRuleErr(err) {\n\t\treturn existingRule, nil // idempotent apply: rule already present\n\t}\n\treturn fmt.Errorf(\"creating rule: %w\", err)\n}","preventionTips":["Make applies idempotent by treating 409 duplicates as success","Validate port ranges and protocols against Neutron's rules before creating","Check security-group rule quota before bulk rule creation","Ensure remote security group IDs are resolved/verified before use"],"tags":["openstack","neutron","security-group","rule-conflict"],"backgroundTag":"openstack-resource-conflict-409","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}