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.
Solutions
- 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.
- Update/reconfigure LocalStack (or the STS-mocking proxy) to return ARNs containing a 12-digit account ID.
- Bypass any TLS-intercepting corporate proxy for sts.<region>.amazonaws.com and retry.
- 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
- Assert 'aws sts get-caller-identity' returns a 12-digit Account before provisioning.
- Remove placeholder STS mocks/proxies (LocalStack, corporate gateways) from production paths.
- Pin and test the AWS endpoint configuration used by kOps in CI.
- Treat any STS response without a valid account ID as a broken environment, not a retryable error.
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
- arn contains too few slashes
- arn has unrecognized type
- failed to parse GetCallerIdentity ARN
- arn does not contain acceptable node role
- AWS partition was empty
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/d9a6b814de605e91.
Report an issue: GitHub.
Appendix: 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)