{"record":{"id":"6ebd15a86b51d006","repo":"kubernetes/kops","slug":"error-updating-iamrole-v","errorCode":null,"errorMessage":"error updating IAMRole: %v","messagePattern":"error updating IAMRole: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/awstasks/iamrole.go","lineNumber":287,"sourceCode":"\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"error reading actual policy document: %v\", err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif actualPolicy == policy {\n\t\t\t\tklog.Warning(\"Policies were actually the same\")\n\t\t\t} else {\n\t\t\t\td := diff.FormatDiff(actualPolicy, policy)\n\t\t\t\tklog.V(2).Infof(\"diff: %s\", d)\n\t\t\t}\n\n\t\t\trequest := &iam.UpdateAssumeRolePolicyInput{}\n\t\t\trequest.PolicyDocument = aws.String(policy)\n\t\t\trequest.RoleName = e.Name\n\n\t\t\t_, err = t.Cloud.IAM().UpdateAssumeRolePolicy(ctx, request)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"error updating IAMRole: %v\", err)\n\t\t\t}\n\t\t}\n\t\tif changes.PermissionsBoundary != nil {\n\t\t\tklog.V(2).Infof(\"Updating IAMRole PermissionsBoundary %q\", *e.Name)\n\n\t\t\trequest := &iam.PutRolePermissionsBoundaryInput{}\n\t\t\trequest.RoleName = e.Name\n\t\t\trequest.PermissionsBoundary = e.PermissionsBoundary\n\n\t\t\tif _, err := t.Cloud.IAM().PutRolePermissionsBoundary(ctx, request); err != nil {\n\t\t\t\treturn fmt.Errorf(\"error updating IAMRole: %v\", err)\n\t\t\t}\n\t\t} else if a.PermissionsBoundary != nil && e.PermissionsBoundary == nil {\n\t\t\trequest := &iam.DeleteRolePermissionsBoundaryInput{}\n\t\t\trequest.RoleName = e.Name\n\n\t\t\tif _, err := t.Cloud.IAM().DeleteRolePermissionsBoundary(ctx, request); err != nil {\n\t\t\t\treturn fmt.Errorf(\"error updating IAMRole: %v\", err)","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/awstasks/iamrole.go#L269-L305","documentation":"When the trust (assume-role) policy changed, RenderAWS calls IAM UpdateAssumeRolePolicy with the newly rendered document. Any AWS error is wrapped as 'error updating IAMRole: %v' (same message text as the permissions-boundary update paths, so read the inner AWS error to disambiguate).","triggerScenarios":"UpdateAssumeRolePolicy returns MalformedPolicyDocument (invalid JSON, wrong Principal/Action shapes, unsupported version), NoSuchEntity (role deleted concurrently), AccessDenied (missing iam:UpdateAssumeRolePolicy), or throttling.","commonSituations":"Hand-edited trust policy in the cluster spec with a typo; adding a condition or service principal AWS rejects (e.g. wrong format for ec2.amazonaws.com); IAM propagation immediately after role creation; SCPs restricting iam:Update* in restricted accounts.","solutions":["Run with klog V=2 to see the rendered policy, then validate it against the IAM policy grammar","Check the inner error for MalformedPolicyDocument and fix Version (\"2012-10-17\"), Effect, Principal, Action fields","For NoSuchEntity, re-run apply so kOps recreates the role first","Grant iam:UpdateAssumeRolePolicy to the credentials and retry after transient throttling"],"exampleFix":"// before: missing/old version and bad principal shape\n{\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":\"ec2.amazonaws.com\",\"Action\":\"sts:AssumeRole\"}]}\n\n// after\n{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"ec2.amazonaws.com\"},\"Action\":\"sts:AssumeRole\"}]}","handlingStrategy":"validation","validationCode":"var doc struct {\n    Version   string `json:\"Version\"`\n    Statement []struct {\n        Effect    string      `json:\"Effect\"`\n        Principal interface{} `json:\"Principal\"`\n        Action    interface{} `json:\"Action\"`\n    } `json:\"Statement\"`\n}\nif err := json.Unmarshal([]byte(trustPolicyJSON), &doc); err != nil { return err }\nif doc.Version != \"2012-10-17\" { return fmt.Errorf(\"unsupported policy Version %q\", doc.Version) }","typeGuard":null,"tryCatchPattern":"_, err := t.Cloud.IAM().UpdateAssumeRolePolicy(ctx, request)\nif err != nil {\n    var mpd *iam.MalformedPolicyDocumentException\n    if errors.As(err, &mpd) { /* log full policy, fix grammar */ }\n    if strings.Contains(err.Error(), \"RequestLimitExceeded\") { /* backoff + retry */ }\n    return err\n}","preventionTips":["Run kOps with -v=2 to capture the exact policy AWS rejected","Validate trust policies with the IAM policy simulator in CI","Keep trust-policy principals in canonical form ({\"Service\":\"ec2.amazonaws.com\"})","Retry updates briefly after role creation to ride out IAM propagation"],"tags":["aws","iam","go","policy"],"backgroundTag":"malformed-policy-document","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"}