kubernetes/kops · error

AWS account id was empty

Error message

AWS account id was empty

What it means

kOps validates that the ARN returned by GetCallerIdentity carries a non-empty AccountID (aws_cloud.go:2120). The ARN parsed fine, but its account-id component is blank, so kOps cannot determine which AWS account it is deploying into. This guards against broken or synthetic STS responses before any resources are created.

Source

Thrown at upup/pkg/fi/cloudup/awsup/aws_cloud.go:2120

	return &resp.InstanceTypes[0], nil
}

// AccountInfo returns the AWS account ID and AWS partition that we are deploying into
func (c *awsCloudImplementation) AccountInfo(ctx context.Context) (string, string, error) {
	request := &sts.GetCallerIdentityInput{}

	response, err := c.sts.GetCallerIdentity(ctx, request)
	if err != nil {
		return "", "", fmt.Errorf("error getting AWS account ID: %v", err)
	}

	arn, err := arn.Parse(aws.ToString(response.Arn))
	if err != nil {
		return "", "", fmt.Errorf("failed to parse GetCallerIdentity ARN: %w", err)
	}

	if arn.AccountID == "" {
		return "", "", fmt.Errorf("AWS account id was empty")
	}
	if arn.Partition == "" {
		return "", "", fmt.Errorf("AWS partition was empty")
	}
	return arn.AccountID, arn.Partition, nil
}

// GetRolesInInstanceProfile return role names which are associated with the instance profile specified by profileName.
func GetRolesInInstanceProfile(c AWSCloud, profileName string) ([]string, error) {
	output, err := c.IAM().GetInstanceProfile(context.TODO(), &iam.GetInstanceProfileInput{
		InstanceProfileName: aws.String(profileName),
	})
	if err != nil {
		return nil, err
	}
	var roleNames []string
	for _, role := range output.InstanceProfile.Roles {
		roleNames = append(roleNames, *role.RoleName)

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Verify real STS output: 'aws sts get-caller-identity' should show an Account field; if using a fake endpoint, fix or remove the endpoint override.
  2. Update/reconfigure LocalStack (or the STS-mocking proxy) to return ARNs containing a 12-digit account ID.
  3. Bypass any TLS-intercepting corporate proxy for sts.<region>.amazonaws.com and retry.
  4. Re-run kOps with the standard AWS environment (no AWS_ENDPOINT_URL overrides) to confirm normal behavior.

Example fix

// before (endpoint config)
EndpointResolver: custom STS mock returning "arn:aws:iam:::user/test"
// after
EndpointResolver: nil  // default sts.<region>.amazonaws.com
Defensive patterns

Strategy: validation

Validate before calling

// confirm the account component exists before calling AccountInfo-dependent code
func arnHasAccount(arnStr string) bool {
	parsed, err := arn.Parse(arnStr)
	return err == nil && parsed.AccountID != ""
}
// CLI equivalent: aws sts get-caller-identity --query Account --output text | grep -E '^[0-9]{12}$'

Type guard

func isEmptyAccountID(err error) bool {
	return err != nil && strings.Contains(err.Error(), "AWS account id was empty")
}

Try / catch

accountID, _, err := cloud.AccountInfo(ctx)
if err != nil {
	if isEmptyAccountID(err) {
		return fmt.Errorf("STS identity has no account ID; endpoint override or STS-compatible service misconfigured")
	}
	return err
}

Prevention

When it happens

Trigger: arn.Parse succeeded but arn.AccountID == "" — e.g. an ARN like 'arn:aws:iam:::user/x' with a missing account id, produced by a misbehaving STS-compatible endpoint, LocalStack, or an intercepted/proxied response.

Common situations: Using LocalStack or a corporate gateway that returns placeholder ARNs without account IDs; custom CA/proxy mangling the STS response; misconfigured endpoint override during kops create cluster.

Related errors


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