kubernetes/kops · error

error creating IAMRole: %v

Error message

error creating IAMRole: %v

What it means

RenderAWS builds a CreateRoleInput (name, assume-role policy document, optional permissions boundary) and calls IAM CreateRole. Any AWS error is logged with the rendered policy at klog V(2) and wrapped as 'error creating IAMRole: %v', so enabling V=2 logging shows the exact document AWS rejected.

Source

Thrown at upup/pkg/fi/cloudup/awstasks/iamrole.go:256

		return fmt.Errorf("error rendering RolePolicyDocument: %v", err)
	}

	if a == nil {
		klog.V(2).Infof("Creating IAMRole with Name:%q", *e.Name)

		request := &iam.CreateRoleInput{}
		request.AssumeRolePolicyDocument = aws.String(policy)
		request.RoleName = e.Name
		request.Tags = mapToIAMTags(e.Tags)

		if e.PermissionsBoundary != nil {
			request.PermissionsBoundary = e.PermissionsBoundary
		}

		response, err := t.Cloud.IAM().CreateRole(ctx, request)
		if err != nil {
			klog.V(2).Infof("IAMRole policy: %s", policy)
			return fmt.Errorf("error creating IAMRole: %v", err)
		}

		e.ID = response.Role.RoleId
	} else {
		if changes.RolePolicyDocument != nil {
			klog.V(2).Infof("Updating IAMRole AssumeRolePolicy %q", *e.Name)

			var err error

			actualPolicy := ""
			if a.RolePolicyDocument != nil {
				actualPolicy, err = fi.ResourceAsString(a.RolePolicyDocument)
				if err != nil {
					return fmt.Errorf("error reading actual policy document: %v", err)
				}
			}

			if actualPolicy == policy {

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Check the wrapped AWS code: for EntityAlreadyExists import/adopt or delete the pre-existing role, then retry
  2. Validate the trust policy JSON has a valid Statement with Effect/Principal/Action (klog V=2 prints it)
  3. For LimitExceeded delete unused roles or request an IAM quota increase
  4. Verify credentials have iam:CreateRole and that no SCP denies it

Example fix

// before: malformed trust principal
"Principal": {"AWS": "arn:aws:iam::123456789012:root/*"}

// after: valid principal
"Principal": {"AWS": "arn:aws:iam::123456789012:root"}
Defensive patterns

Strategy: try-catch

Validate before calling

// validate trust policy + name availability before create
var doc map[string]interface{}
if err := json.Unmarshal([]byte(trustPolicyJSON), &doc); err != nil { return err }
_, err := iamClient.GetRole(&iam.GetRoleInput{RoleName: aws.String(roleName)})
if err == nil { return fmt.Errorf("role %s already exists; import or delete it first", roleName) }

Try / catch

_, err := t.Cloud.IAM().CreateRole(ctx, request)
if err != nil {
    var aee *iam.EntityAlreadyExistsException
    if errors.As(err, &aee) { /* adopt or delete existing role */ }
    klog.V(2).Infof("IAMRole policy: %s", policy) // inspect rejected document
    return err
}

Prevention

When it happens

Trigger: CreateRole returns EntityAlreadyExists (name taken by another role in the account), MalformedPolicyDocument (invalid trust policy JSON or wrong principal format), LimitExceeded (role count quota), AccessDenied (missing iam:CreateRole), or InvalidInput for a malformed permissions-boundary ARN.

Common situations: Recreating a cluster in an account where a role of the same name persists; trust policy with a wrong ARN/principal shape; org-level service control policies denying iam:CreateRole; account hitting IAM role limits.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/6e96350c554095a4. Report an issue: GitHub.