kubernetes/kops · error

found %d Nat Gateways with ID %q, expected 1

Error message

found %d Nat Gateways with ID %q, expected 1

What it means

After describing a NAT gateway by ID, Find() requires exactly one result; this error fires when the ID matched zero or multiple gateways. Since DescribeNatGateways filters by a specific ID, 0 results means the gateway was deleted, and >1 is an AWS-side invariant violation; either way kOps cannot map the stored ID to current state.

Source

Thrown at upup/pkg/fi/cloudup/awstasks/natgateway.go:83

	cloud := awsup.GetCloud(c)
	var ngw *ec2types.NatGateway
	actual := &NatGateway{}

	if fi.ValueOf(e.ID) != "" {
		// We have an existing NGW, lets look up the EIP
		ngwIds := []string{fi.ValueOf(e.ID)}

		request := &ec2.DescribeNatGatewaysInput{
			NatGatewayIds: ngwIds,
		}

		response, err := cloud.EC2().DescribeNatGateways(ctx, request)
		if err != nil {
			return nil, fmt.Errorf("error listing Nat Gateways %v", err)
		}

		if len(response.NatGateways) != 1 {
			return nil, fmt.Errorf("found %d Nat Gateways with ID %q, expected 1", len(response.NatGateways), fi.ValueOf(e.ID))
		}
		ngw = &response.NatGateways[0]

		if len(ngw.NatGatewayAddresses) != 1 {
			return nil, fmt.Errorf("found %d EIP Addresses for 1 NATGateway, expected 1", len(ngw.NatGatewayAddresses))
		}
	} else {
		// This is the normal/default path
		var err error
		ngw, err = e.findNatGateway(c)
		if err != nil {
			return nil, err
		}
		if ngw == nil {
			return nil, nil
		}
	}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Confirm the gateway ID exists: aws ec2 describe-nat-gateways --nat-gateway-ids ngw-xxx
  2. If deleted intentionally, run kops update cluster to recreate it (clear stale ID from state)
  3. Check you are operating in the correct region and account
  4. If 0 results after deletion, recreate via kops rather than restoring manually to keep state consistent

Example fix

// before: gateway deleted manually, kops still references it
// after
kops update cluster --name mycluster.k8s.local --yes  # recreates NAT gateway and fixes state
Defensive patterns

Strategy: validation

Validate before calling

out, _ := cloud.EC2().DescribeNatGateways(ctx, &ec2.DescribeNatGatewaysInput{NatGatewayIds: []string{id}})
if out == nil || len(out.NatGateways) == 0 {
  return errors.New("referenced NAT gateway no longer exists; run kops update cluster to recreate")
}

Try / catch

if len(response.NatGateways) != 1 {
  return fmt.Errorf("stale NAT gateway ID %s: found %d, expected 1 — recreate via kops update", id, len(response.NatGateways))
}

Prevention

When it happens

Trigger: e.ID is set but the NAT gateway no longer exists (deleted out-of-band or in another region/account), yielding 0 results; >1 is theoretically impossible with an ID filter but is defensively checked.

Common situations: NAT gateway manually deleted in console during a maintenance window; kOps state pointing at an old cluster's gateway; region misconfiguration making the ID unresolvable.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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