kubernetes/kops · error
error parsing expected RolePolicyDocument for IAMRole %q: %v
Error message
error parsing expected RolePolicyDocument for IAMRole %q: %v
What it means
Find() parses the expected RolePolicyDocument as JSON so it can compare semantically against the actual policy. If the expected content is not valid JSON, the parse error is wrapped with the role name. This is a spec/template problem, not an AWS problem.
Source
Thrown at upup/pkg/fi/cloudup/awstasks/iamrole.go:103
if r.AssumeRolePolicyDocument != nil {
// The AssumeRolePolicyDocument is URI encoded (?)
actualPolicy := *r.AssumeRolePolicyDocument
actualPolicy, err = url.QueryUnescape(actualPolicy)
if err != nil {
return nil, fmt.Errorf("error parsing AssumeRolePolicyDocument for IAMRole %s: %v", *e.Name, err)
}
// The RolePolicyDocument is reformatted by AWS
// We parse both as JSON; if the json forms are equal we pretend the actual value is the expected value
if e.RolePolicyDocument != nil {
expectedPolicy, err := fi.ResourceAsString(e.RolePolicyDocument)
if err != nil {
return nil, fmt.Errorf("error reading expected RolePolicyDocument for IAMRole %q: %v", aws.ToString(e.Name), err)
}
expectedJson := make(map[string]interface{})
err = json.Unmarshal([]byte(expectedPolicy), &expectedJson)
if err != nil {
return nil, fmt.Errorf("error parsing expected RolePolicyDocument for IAMRole %q: %v", aws.ToString(e.Name), err)
}
actualJson := make(map[string]interface{})
err = json.Unmarshal([]byte(actualPolicy), &actualJson)
if err != nil {
return nil, fmt.Errorf("error parsing actual RolePolicyDocument for IAMRole %q: %v", aws.ToString(e.Name), err)
}
if reflect.DeepEqual(actualJson, expectedJson) {
klog.V(2).Infof("actual RolePolicyDocument was json-equal to expected; returning expected value")
actualPolicy = expectedPolicy
}
}
actual.RolePolicyDocument = fi.NewStringResource(actualPolicy)
}
actual.Tags = mapIAMTagsToMap(r.Tags)
klog.V(2).Infof("found matching IAMRole %q", aws.ToString(actual.ID))View on GitHub (pinned to 4c8573c808)
Solutions
- Validate the policy JSON locally (jq . policy.json) before applying the cluster spec
- Fix the template or manifest producing the invalid JSON (remove comments/commas, ensure variables resolve)
- Regenerate the manifest with kops replace/update using a known-good template
- Pin the kops version to one consistent with the stored cluster spec
Example fix
// before (invalid JSON with comment)
{"Version":"2012-10-17" /* comment */}
// after
{"Version":"2012-10-17"} Defensive patterns
Strategy: validation
Validate before calling
// lint expected policy JSON before apply
var buf map[string]interface{}
if err := json.Unmarshal([]byte(expectedPolicy), &buf); err != nil {
return fmt.Errorf("expected RolePolicyDocument is not valid JSON: %w", err)
} Type guard
func isJSON(s string) bool { var v interface{}; return json.Unmarshal([]byte(s), &v) == nil } Prevention
- Run jq/jsonlint on policy templates before kops update
- Avoid comments and trailing commas in policy templates
- Ensure template variables resolve to real values
- Store policies as .json files validated in CI
When it happens
Trigger: json.Unmarshal([]byte(expectedPolicy), &expectedJson) fails because the template produced invalid JSON (trailing commas, comments, unquoted keys, truncated output).
Common situations: Hand-edited trust policy template in the cluster spec; Go template placeholders left unresolved; kOps version mismatch generating malformed policy; file truncated in state store.
Related errors
- error parsing actual RolePolicyDocument for IAMRole %q: %v
- error inline policy: %w
- additionalPolicy %q is invalid: %v
- error parsing AssumeRolePolicyDocument for IAMRole %s: %v
- role name length must be equal to 64 or less: %q
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/8d08e920828dc37a.
Report an issue: GitHub.