{"record":{"id":"4307f0dc2fe2527d","repo":"kubernetes/kops","slug":"error-deleting-iamrolepolicy-v","errorCode":null,"errorMessage":"error deleting IAMRolePolicy: %v","messagePattern":"error deleting IAMRolePolicy: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/awstasks/iamrolepolicy.go","lineNumber":241,"sourceCode":"\n\t\treturn nil\n\t}\n\n\tif policy == \"\" {\n\t\t// A deletion\n\n\t\trequest := &iam.DeleteRolePolicyInput{}\n\t\trequest.RoleName = e.Role.Name\n\t\trequest.PolicyName = e.Name\n\n\t\tklog.V(2).Infof(\"Deleting role policy %s/%s\", aws.ToString(e.Role.Name), aws.ToString(e.Name))\n\t\t_, err = t.Cloud.IAM().DeleteRolePolicy(ctx, request)\n\t\tif err != nil {\n\t\t\tif awsup.IsIAMNoSuchEntityException(err) {\n\t\t\t\tklog.V(2).Infof(\"Got NoSuchEntity deleting role policy %s/%s; assuming does not exist\", aws.ToString(e.Role.Name), aws.ToString(e.Name))\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"error deleting IAMRolePolicy: %v\", err)\n\t\t}\n\t\treturn nil\n\t}\n\n\tdoPut := false\n\n\tif a == nil {\n\t\tklog.V(2).Infof(\"Creating IAMRolePolicy\")\n\t\tdoPut = true\n\t} else if changes != nil {\n\t\tif changes.PolicyDocument != nil {\n\t\t\tklog.V(2).Infof(\"Applying changed role policy to %q:\", *e.Name)\n\n\t\t\tactualPolicy, err := a.policyDocumentString()\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"error reading actual policy document: %v\", err)\n\t\t\t}\n","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/awstasks/iamrolepolicy.go#L223-L259","documentation":"When the rendered inline policy is empty, RenderAWS treats it as a deletion and calls DeleteRolePolicy. If AWS returns an error other than NoSuchEntity (already gone), kops wraps it as 'error deleting IAMRolePolicy' and aborts convergence.","triggerScenarios":"DeleteRolePolicy fails with e.g. AccessDenied, LimitExceeded (too many inline policies during cleanup), throttling, or concurrency errors while removing a role's inline policy.","commonSituations":"Credentials lacking iam:DeleteRolePolicy; another controller/process deleting the same policy concurrently; IAM API throttling; deleted role returning unexpected (non-NoSuchEntity) errors.","solutions":["Read the wrapped AWS error for the specific cause","Grant iam:DeleteRolePolicy to the kops credentials","Re-run `kops update cluster` — NoSuchEntity is tolerated, so races usually resolve on retry","Check whether the role/policy is concurrently managed by CloudFormation or another tool"],"exampleFix":"// IAM policy allowing lifecycle operations\n{\n  \"Effect\": \"Allow\",\n  \"Action\": [\"iam:PutRolePolicy\",\"iam:GetRolePolicy\",\"iam:DeleteRolePolicy\"],\n  \"Resource\": \"*\"\n}","handlingStrategy":"retry","validationCode":"// pre-check deletion permission\n_, err := iamClient.SimulatePrincipalPolicy(ctx, &iam.SimulatePrincipalPolicyInput{\n  PolicySourceArn: aws.String(kopsRoleArn),\n  ActionNames: []string{\"iam:DeleteRolePolicy\"},\n})","typeGuard":null,"tryCatchPattern":"err := kopsUpdate()\nif err != nil && strings.Contains(err.Error(), \"error deleting IAMRolePolicy\") {\n  if isThrottling(err) || isConcurrentMutation(err) {\n    time.Sleep(backoff); retry(kopsUpdate)\n  } // else inspect wrapped AWS error\n}","preventionTips":["Grant iam:DeleteRolePolicy to kops credentials","Don't manage the same inline policies with CloudFormation and kops simultaneously","Serialize kops runs against the same cluster","Rely on NoSuchEntity tolerance: empty-policy deletions are safe to retry"],"tags":["aws","iam","delete-policy"],"backgroundTag":"aws-iam-api-error","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"}