kubernetes/kops · error

too many reservations returned for the single instance-id

Error message

too many reservations returned for the single instance-id

What it means

GetInstanceCertificateNames expects the EC2 DescribeInstances output — queried by instance-id — to contain exactly one reservation. If len(instances.Reservations) != 1 (including zero), the result does not correspond to a single instance lookup and the function refuses to derive certificate names. The message says 'too many' but it also fires when zero reservations come back.

Source

Thrown at pkg/bootstrap/awsbootstrap/verifier.go:494

// buildSTSRequestValidator determines the form of a valid STS presigned URL.
func buildSTSRequestValidator(ctx context.Context, stsClient *sts.Client) (*stsRequestValidator, error) {
	// We build a presigned token ourselves, primarily to get the expected hostname for the endpoint.
	signed, err := sts.NewPresignClient(stsClient).PresignGetCallerIdentity(ctx, &sts.GetCallerIdentityInput{})
	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

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Ensure DescribeInstances is called with InstanceIds: []string{instanceID} so exactly one reservation is expected
  2. Check the verifier's EC2 client region and credentials can actually see the instance (cross-account/region lookups return empty)
  3. Log len(instances.Reservations) and the caller identity to distinguish the zero-case (not found) from the many-case
  4. Re-run the bootstrap after confirming the instance is running and visible in the target account

Example fix

// before
out, err := ec2Client.DescribeInstances(ctx, &ec2.DescribeInstancesInput{})
// after
out, err := ec2Client.DescribeInstances(ctx, &ec2.DescribeInstancesInput{
  InstanceIds: []string{instanceID},
})
Defensive patterns

Strategy: validation

Validate before calling

if out == nil || len(out.Reservations) != 1 {
  return fmt.Errorf("expected exactly 1 reservation for instance %s, got %d", instanceID, len(out.Reservations))
}

Type guard

func isSingleReservation(out *ec2.DescribeInstancesOutput) bool {
  return out != nil && len(out.Reservations) == 1
}

Try / catch

addrs, err := GetInstanceCertificateNames(out)
if err != nil {
  return fmt.Errorf("describing instance %s: %w", instanceID, err)
}

Prevention

When it happens

Trigger: verifyCallerIdentity calls GetInstanceCertificateNames with a DescribeInstancesOutput whose Reservations slice has length 0 (instance not found / not visible) or greater than 1 (query returned multiple reservations).

Common situations: The caller identity's instance-id no longer exists (terminated instance racing the check); IAM policies restrict DescribeInstances so the instance is invisible; filtering by instance-id was dropped so the whole account's reservations are returned; instance in a different account/region than the verifier's EC2 client.

Related errors


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