{"record":{"id":"a9a028ac12a30962","repo":"kubernetes/kops","slug":"too-many-instances-returned-for-the-single-instanc","errorCode":null,"errorMessage":"too many instances returned for the single instance-id","messagePattern":"too many instances returned for the single instance-id","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/bootstrap/awsbootstrap/verifier.go","lineNumber":498,"sourceCode":"\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"building presigned request: %w\", err)\n\t}\n\tu, err := url.Parse(signed.URL)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"parsing presigned url: %w\", err)\n\t}\n\treturn &stsRequestValidator{Host: u.Host}, nil\n}\n\n// GetInstanceCertificateNames returns the instance names and addresses that should go into\n// certificates: the instance ID, the private DNS name and the IP addresses.\nfunc GetInstanceCertificateNames(instances *ec2.DescribeInstancesOutput) (addrs []string, err error) {\n\tif len(instances.Reservations) != 1 {\n\t\treturn nil, fmt.Errorf(\"too many reservations returned for the single instance-id\")\n\t}\n\n\tif len(instances.Reservations[0].Instances) != 1 {\n\t\treturn nil, fmt.Errorf(\"too many instances returned for the single instance-id\")\n\t}\n\n\tinstance := instances.Reservations[0].Instances[0]\n\n\taddrs = append(addrs, *instance.InstanceId)\n\n\tif instance.PrivateDnsName != nil {\n\t\taddrs = append(addrs, *instance.PrivateDnsName)\n\t}\n\n\t// We only use data for the first interface, and only the first IP\n\tfor _, iface := range instance.NetworkInterfaces {\n\t\tif iface.Attachment == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif *iface.Attachment.DeviceIndex != 0 {\n\t\t\tcontinue\n\t\t}","sourceCodeStart":480,"sourceCodeEnd":516,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/bootstrap/awsbootstrap/verifier.go#L480-L516","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nout, err := ec2Client.DescribeInstances(ctx, &ec2.DescribeInstancesInput{Filters: filters})\n// after\nout, err := ec2Client.DescribeInstances(ctx, &ec2.DescribeInstancesInput{\n  InstanceIds: []string{instanceID}, // exactly one instance expected\n})","handlingStrategy":"validation","validationCode":"if len(out.Reservations) != 1 || len(out.Reservations[0].Instances) != 1 {\n  return fmt.Errorf(\"expected exactly 1 instance in reservation, got %d\", len(out.Reservations[0].Instances))\n}","typeGuard":"func isSingleInstance(out *ec2.DescribeInstancesOutput) bool {\n  return out != nil && len(out.Reservations) == 1 && len(out.Reservations[0].Instances) == 1\n}","tryCatchPattern":"addrs, err := GetInstanceCertificateNames(out)\nif err != nil {\n  return fmt.Errorf(\"cannot derive cert names: %w\", err)\n}","preventionTips":["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"],"tags":["aws","ec2","bootstrap","instance-lookup"],"backgroundTag":"unexpected-ec2-describe-result","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}