kubernetes/kops · error
found multiple NatGateways with id %q
Error message
found multiple NatGateways with id %q
What it means
After DescribeNatGateways by a single ID, the code asserts exactly one result. EC2 should return at most one gateway per ID, so more than one result indicates an unexpected API response and the code refuses to proceed.
Source
Thrown at upup/pkg/fi/cloudup/awstasks/natgateway.go:200
}
return nil, nil
}
func findNatGatewayById(ctx context.Context, cloud awsup.AWSCloud, id string) (*ec2types.NatGateway, error) {
request := &ec2.DescribeNatGatewaysInput{}
request.NatGatewayIds = []string{id}
response, err := cloud.EC2().DescribeNatGateways(ctx, request)
if err != nil {
return nil, fmt.Errorf("error listing NatGateway %q: %v", id, err)
}
if response == nil || len(response.NatGateways) == 0 {
klog.V(2).Infof("Unable to find NatGateway %q", id)
return nil, nil
}
if len(response.NatGateways) != 1 {
return nil, fmt.Errorf("found multiple NatGateways with id %q", id)
}
return &response.NatGateways[0], nil
}
func findNatGatewayFromRouteTable(ctx context.Context, cloud awsup.AWSCloud, routeTable *RouteTable) (*ec2types.NatGateway, error) {
// Find via route on private route table
if routeTable.ID != nil {
klog.V(2).Infof("trying to match NatGateway via RouteTable %s", *routeTable.ID)
rt, err := findRouteTableByID(ctx, cloud, *routeTable.ID)
if err != nil {
return nil, fmt.Errorf("error finding associated RouteTable to NatGateway: %v", err)
}
if rt != nil {
var natGatewayIDs []*string
natGatewayIDsSeen := map[string]bool{}
for _, route := range rt.Routes {
if route.NatGatewayId != nil && route.State != ec2types.RouteStateBlackhole && !natGatewayIDsSeen[*route.NatGatewayId] {View on GitHub (pinned to 4c8573c808)
Solutions
- Re-run the operation — usually a transient API anomaly
- Check for proxies or mocks in front of the EC2 API that might duplicate results
- If reproducible, inspect the raw DescribeNatGateways response and report to AWS support / kops maintainers
Example fix
// before: trusting a duplicated response
// after: dedupe by ID before the count assertion
seen := map[string]bool{}
var uniq []ec2types.NatGateway
for _, g := range response.NatGateways {
if !seen[*g.NatGatewayId] { seen[*g.NatGatewayId] = true; uniq = append(uniq, g) }
} Defensive patterns
Strategy: type-guard
Validate before calling
// assert single result before use
if len(response.NatGateways) != 1 { return fmt.Errorf("expected exactly 1 NatGateway for id %s, got %d", id, len(response.NatGateways)) } Type guard
func exactlyOne(gws []ec2types.NatGateway) *ec2types.NatGateway {
if len(gws) == 1 { return &gws[0] }
return nil
} Try / catch
gw, err := findNatGatewayById(ctx, cloud, id)
if err != nil && strings.Contains(err.Error(), "found multiple NatGateways with id") {
// transient/anomalous API response — retry once, then investigate
} Prevention
- Retry once on anomalous DescribeNatGateways responses
- Avoid custom proxies/mocks in front of EC2 in production tooling
When it happens
Trigger: DescribeNatGateways called with request.NatGatewayIds = [id] returns len(response.NatGateways) > 1, i.e. the API returned multiple NatGateway entries for one ID (response==nil or empty is handled separately).
Common situations: Practically only seen during AWS API anomalies, mocked/test EC2 implementations, or custom clients returning duplicate pages; rarely in production.
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- found multiple tags for: %v
- error listing NatGateway %q: %v
- Could not find '%s' tag from route table
- found multiple kOps NatGateways in route table %s
- Error creating Nat Gateway: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/162eaeb0f9a319cd.
Report an issue: GitHub.