{"record":{"id":"bb5a3f64a1ca3c13","repo":"kubernetes/kops","slug":"error-reading-actual-policy-document-v","errorCode":null,"errorMessage":"error reading actual policy document: %v","messagePattern":"error reading actual policy document: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/awstasks/iamrole.go","lineNumber":270,"sourceCode":"\n\t\tresponse, err := t.Cloud.IAM().CreateRole(ctx, request)\n\t\tif err != nil {\n\t\t\tklog.V(2).Infof(\"IAMRole policy: %s\", policy)\n\t\t\treturn fmt.Errorf(\"error creating IAMRole: %v\", err)\n\t\t}\n\n\t\te.ID = response.Role.RoleId\n\t} else {\n\t\tif changes.RolePolicyDocument != nil {\n\t\t\tklog.V(2).Infof(\"Updating IAMRole AssumeRolePolicy %q\", *e.Name)\n\n\t\t\tvar err error\n\n\t\t\tactualPolicy := \"\"\n\t\t\tif a.RolePolicyDocument != nil {\n\t\t\t\tactualPolicy, err = fi.ResourceAsString(a.RolePolicyDocument)\n\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}","sourceCodeStart":252,"sourceCodeEnd":288,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/awstasks/iamrole.go#L252-L288","documentation":"During update comparison, RenderAWS re-renders the existing (actual) task's RolePolicyDocument with fi.ResourceAsString to diff it against the desired policy. If rendering the actual resource fails (template execution or resource conversion), it returns 'error reading actual policy document: %v'. A nil actual resource is handled — only a non-nil unrenderable resource reaches this error.","triggerScenarios":"The actual (a.RolePolicyDocument) task was populated from state as a TemplateResource whose template now fails to execute — typically after a kOps upgrade changed template context variables, or a custom template resource with bad syntax was applied previously.","commonSituations":"Applying a cluster spec built by a different kOps version whose stored template references removed fields; hand-crafted fi.TemplateResource with typos; stale state store snapshot of the task.","solutions":["Read the inner error to find the failing template key or syntax issue","Run kops replace -f with a corrected policy document or upgrade kOps so both sides render with the same context","If the state store task snapshot is stale/corrupt, use kops toolbox dump to inspect and re-apply a fixed spec","Avoid custom TemplateResources for policy docs; use literal string resources so rendering cannot fail"],"exampleFix":"// before: custom template resource in actual state\nRolePolicyDocument: fi.NewTemplateResource(\"policies\", \"{{ .OldField }}\")\n\n// after: literal document, render cannot fail\nRolePolicyDocument: fi.NewStringResource(renderedJSON)","handlingStrategy":"validation","validationCode":"if a.RolePolicyDocument != nil {\n    actualPolicy, err := fi.ResourceAsString(a.RolePolicyDocument)\n    if err != nil {\n        // fall back: refetch from AWS instead of failing the diff\n        return fetchPolicyFromAWS(roleName)\n    }\n    _ = actualPolicy\n}","typeGuard":"func canDiff(actual, desired fi.Resource) bool {\n    _, e1 := fi.ResourceAsString(actual)\n    _, e2 := fi.ResourceAsString(desired)\n    return e1 == nil && e2 == nil\n}","tryCatchPattern":null,"preventionTips":["Store policy documents as literal resources, not templates, so diffs always render","Keep kOps and the state store version-aligned; migrate specs on upgrade","Snapshot-test RenderAWS with real cluster specs to catch template drift","If a diff fails after upgrade, re-apply a corrected spec rather than hacking state"],"tags":["aws","iam","go","template"],"backgroundTag":"policy-template-render-failed","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"}