kubernetes/kops · error
too many instances returned for the single instance-id
Error message
too many instances returned for the single instance-id
What it means
GetInstanceCertificateNames requires the single returned reservation to contain exactly one instance. If len(instances.Reservations[0].Instances) != 1, the DescribeInstances response does not match the assumed one-instance lookup, so certificate SANs cannot be derived safely.
Source
Thrown at pkg/bootstrap/awsbootstrap/verifier.go:498
if err != nil {
return nil, fmt.Errorf("building presigned request: %w", err)
}
u, err := url.Parse(signed.URL)
if err != nil {
return nil, fmt.Errorf("parsing presigned url: %w", err)
}
return &stsRequestValidator{Host: u.Host}, nil
}
// GetInstanceCertificateNames returns the instance names and addresses that should go into
// certificates: the instance ID, the private DNS name and the IP addresses.
func GetInstanceCertificateNames(instances *ec2.DescribeInstancesOutput) (addrs []string, err error) {
if len(instances.Reservations) != 1 {
return nil, fmt.Errorf("too many reservations returned for the single instance-id")
}
if len(instances.Reservations[0].Instances) != 1 {
return nil, fmt.Errorf("too many instances returned for the single instance-id")
}
instance := instances.Reservations[0].Instances[0]
addrs = append(addrs, *instance.InstanceId)
if instance.PrivateDnsName != nil {
addrs = append(addrs, *instance.PrivateDnsName)
}
// We only use data for the first interface, and only the first IP
for _, iface := range instance.NetworkInterfaces {
if iface.Attachment == nil {
continue
}
if *iface.Attachment.DeviceIndex != 0 {
continue
}View on GitHub (pinned to 4c8573c808)
Solutions
- Always filter DescribeInstances by the specific InstanceId from the caller identity
- If zero instances, treat as 'instance not found/terminated' and retry the bootstrap after confirming the node is running
- Log instance IDs in the reservation to identify which instances leaked into the result
- Retry after a short delay — EC2 describe results can lag instance state changes
Example fix
// before
out, err := ec2Client.DescribeInstances(ctx, &ec2.DescribeInstancesInput{Filters: filters})
// after
out, err := ec2Client.DescribeInstances(ctx, &ec2.DescribeInstancesInput{
InstanceIds: []string{instanceID}, // exactly one instance expected
}) Defensive patterns
Strategy: validation
Validate before calling
if len(out.Reservations) != 1 || len(out.Reservations[0].Instances) != 1 {
return fmt.Errorf("expected exactly 1 instance in reservation, got %d", len(out.Reservations[0].Instances))
} Type guard
func isSingleInstance(out *ec2.DescribeInstancesOutput) bool {
return out != nil && len(out.Reservations) == 1 && len(out.Reservations[0].Instances) == 1
} Try / catch
addrs, err := GetInstanceCertificateNames(out)
if err != nil {
return fmt.Errorf("cannot derive cert names: %w", err)
} Prevention
- Filter DescribeInstances by the exact instance id, not by tags/filters that can match many instances
- Handle terminated/racing instances by retrying after a short delay
- Log the reservation contents when validation fails
When it happens
Trigger: verifyCallerIdentity passes a DescribeInstancesOutput where Reservations[0].Instances has zero entries (reservation placeholder with no instances, e.g. terminated instance) or multiple instances (query not filtered to a single instance-id).
Common situations: Instance was terminated between the STS call and DescribeInstances; missing InstanceIds filter returning sibling instances; spot interruption terminating the instance mid-bootstrap; eventual consistency in EC2 right after instance launch.
Related errors
- too many reservations returned for the single instance-id
- failed to get region from ec2 metadata: %w
- missing instance id: %s
- found multiple instances with instance id: %s
- cannot determine challenge endpoint for instance id: %s
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/a9a028ac12a30962.
Report an issue: GitHub.