TerraformPilot

DevOps

Fix Terraform Error - Error Creating NAT Gateway - NotFound

Fix NAT Gateway NotFound errors when Elastic IP is missing or subnet is private. Covers public vs private NAT, EIP allocation, and VPC routing configuration.

LLuca Berton2 min read

Quick Answer

#

The Elastic IP doesn't exist, the subnet is incorrect, or you're mixing public and private NAT Gateway types. Public NAT Gateways need an EIP and a public subnet. Private NAT Gateways don't need an EIP.

The Error

#
Error: creating EC2 NAT Gateway: InvalidElasticIpID.NotFound:
  The elastic-ip ID 'eipalloc-xxx' does not exist
Error: creating EC2 NAT Gateway: InvalidSubnetID.NotFound:
  The subnet ID 'subnet-xxx' does not exist
Error: creating EC2 NAT Gateway: InvalidParameterCombination:
  Connectivity type 'private' does not support allocation IDs

What Causes This Error

#

1. Elastic IP Doesn't Exist

#

The allocation_id references an EIP that was deleted, in a different region, or not yet created.

2. NAT Gateway in a Private Subnet

#

A public NAT Gateway must be in a public subnet (one with a route to an Internet Gateway).

3. Connectivity Type Mismatch

#

Using allocation_id with connectivity_type = "private", or omitting it with the default public type.

4. Missing Internet Gateway

#

The VPC has no Internet Gateway, so the public subnet can't actually route to the internet.

How to Fix It

#

Solution 1: Complete Public NAT Gateway Setup

#
# 1. Internet Gateway
resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id
}
 
# 2. Public subnet with IGW route
resource "aws_subnet" "public" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = "us-east-1a"
  map_public_ip_on_launch = true
  tags = { Name = "public-subnet" }
}
 
resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.main.id
  }
}
 
resource "aws_route_table_association" "public" {
  subnet_id      = aws_subnet.public.id
  route_table_id = aws_route_table.public.id
}
 
# 3. Elastic IP for NAT
resource "aws_eip" "nat" {
  domain = "vpc"
  tags   = { Name = "nat-eip" }
}
 
# 4. NAT Gateway in public subnet
resource "aws_nat_gateway" "main" {
  allocation_id = aws_eip.nat.id
  subnet_id     = aws_subnet.public.id  # Must be PUBLIC
  tags          = { Name = "main-nat" }
 
  depends_on = [aws_internet_gateway.main]
}
 
# 5. Private subnet routes through NAT
resource "aws_route_table" "private" {
  vpc_id = aws_vpc.main.id
  route {
    cidr_block     = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.main.id
  }
}

Solution 2: Private NAT Gateway (No EIP)

#

For VPC-to-VPC traffic without internet access:

resource "aws_nat_gateway" "private" {
  connectivity_type = "private"
  subnet_id         = aws_subnet.private.id
  # No allocation_id needed for private NAT
  tags = { Name = "private-nat" }
}

Solution 3: Multi-AZ NAT Gateways

#
variable "availability_zones" {
  default = ["us-east-1a", "us-east-1b", "us-east-1c"]
}
 
resource "aws_eip" "nat" {
  for_each = toset(var.availability_zones)
  domain   = "vpc"
  tags     = { Name = "nat-${each.key}" }
}
 
resource "aws_nat_gateway" "main" {
  for_each      = toset(var.availability_zones)
  allocation_id = aws_eip.nat[each.key].id
  subnet_id     = aws_subnet.public[each.key].id
 
  depends_on = [aws_internet_gateway.main]
  tags       = { Name = "nat-${each.key}" }
}

Public vs Private NAT Gateway

#
FeaturePublicPrivate
Internet access✅ Yes❌ No
Elastic IP✅ Required❌ Not allowed
Subnet typePublic (IGW route)Private
Use casePrivate instances → internetVPC-to-VPC routing
Cost~$0.045/hr + data~$0.045/hr + data

Troubleshooting Checklist

#
  1. ✅ Does the EIP exist? (aws ec2 describe-addresses --allocation-ids eipalloc-xxx)
  2. ✅ Is the EIP in the same region as the NAT Gateway?
  3. ✅ Is the subnet public? (Has a route to an Internet Gateway?)
  4. ✅ Does the VPC have an Internet Gateway attached?
  5. ✅ Are you mixing public connectivity with missing EIP, or private with an EIP?
  6. ✅ Does depends_on ensure the IGW exists before the NAT?

Prevention Tips

#
  • Always create the EIP in the same Terraform config as the NAT Gateway
  • Use depends_on = [aws_internet_gateway.main] on NAT Gateways
  • Tag subnets clearly as public or private to avoid confusion
  • Use one NAT Gateway per AZ for high availability
  • Consider VPC endpoints for S3/DynamoDB instead of routing through NAT (saves cost)
#

Conclusion

#

NAT Gateway NotFound errors are typically about EIP/subnet mismatches. Public NAT Gateways need an EIP and a public subnet with an Internet Gateway route. Private NAT Gateways don't use EIPs. Always create the EIP and IGW in the same config and use depends_on to enforce creation order.

#Terraform#Troubleshooting#DevOps#Error Fix#Infrastructure as Code

Share this article