Task timed out after 3.00 seconds

Lambda Timeout Calling S3 From VPC Without NAT Gateway

Your private-subnet Lambda can't reach S3 because there's no route out. The fix is a free S3 Gateway Endpoint, not a NAT Gateway.

You put a Lambda in a private subnet, gave it an IAM role with S3 access, and it still dies with "Task timed out after 3.00 seconds" the moment it calls s3:GetObject. IAM is fine. The bucket policy is fine. Your syntax is fine. The problem is that your function has no route to S3.

A private subnet has no internet gateway route. No NAT Gateway means no 0.0.0.0/0 route at all. So when the SDK tries to hit s3.us-east-1.amazonaws.com, the SYN packet goes nowhere and you burn the full timeout window. The Lambda isn't broken — it's isolated by design. You built a subnet with no exit and then acted surprised when nothing could leave.

There are three fixes people reach for. Only one of them is actually correct. Here they are in order of how often I see them applied.

Cause 1: No S3 Gateway Endpoint (the real fix)

This is the fix you want. S3 and DynamoDB support VPC Gateway Endpoints, which are route table entries that point AWS service traffic at the S3 backbone network instead of the public internet. They're free. They don't need a NAT. They don't need an ENI, an IP, or a security group. They just work.

The symptom that screams "I forgot the endpoint" is a Lambda that can talk to other resources in your VPC just fine — RDS, ElastiCache, another internal Lambda — but chokes on every single AWS API call. If it can reach 10.0.0.5 but not s3.amazonaws.com, you're missing a route.

Create the endpoint from the console: VPC → Endpoints → Create endpoint → AWS services → search "s3" → pick com.amazonaws.us-east-1.s3 with type Gateway. Select the route tables for every subnet your Lambda runs in. Attach a policy — the default full-access one is fine for testing, then scope it down.

Or do it from the CLI if you'd rather not click through the wizard:

aws ec2 create-vpc-endpoint \
  --vpc-id vpc-0abc123def456789 \
  --service-name com.amazonaws.us-east-1.s3 \
  --route-table-ids rtb-0111 rtb-0222 rtb-0333 \
  --vpc-endpoint-type Gateway \
  --policy-document file://s3-endpoint-policy.json

That's it. No redeploy of the Lambda. The route table updates propagate in under a minute. Test again and your S3 call returns in 40ms.

Two things people get wrong here. First: you must attach the endpoint to every route table your function might land in. If Lambda scales out to a new AZ and that subnet's route table doesn't have the endpoint route, those invocations fail while the others succeed. Intermittent timeouts are almost always this. Second: the endpoint policy is separate from your Lambda's IAM role. Both have to allow the action. A restrictive endpoint policy will silently break things while IAM looks perfectly fine in CloudTrail.

Cause 2: Lambda in a Public Subnet Without a Public IP Problem

This one is sneakier and it catches people who think "public subnet = internet access." A subnet is public because its route table has a 0.0.0.0/0 route to an Internet Gateway. But a Lambda ENI in that subnet doesn't get a public IP by default. Lambda doesn't assign public IPs to Hyperplane ENIs. So you've got the route, but no address to translate from.

Symptom: the function times out on S3, and you swear the subnet is public, and it is. It just doesn't matter.

You have two options. The correct one is to put the Lambda back in a private subnet and use the Gateway Endpoint from Cause 1. The other option is to add a NAT Gateway so the private subnet has outbound internet, then keep the function private.

The NAT Gateway option costs roughly $32/month in us-east-1 before data processing, per AZ. If someone on your team suggested this as the first move, they cost you $400/year to solve a problem a free endpoint fixes in five minutes. Don't do this for S3. Do it only if your Lambda genuinely needs to reach the public internet for something else — a third-party API, for example.

If you do add a NAT, the route table for the private subnet needs:

Destination: 0.0.0.0/0
Target: nat-0abc123def456789

And the NAT lives in a public subnet with its own IGW route. Miss either piece and you're back to timeouts.

Rule of thumb: if the destination is an AWS service with a Gateway Endpoint, use the endpoint. NAT is for third-party traffic. Don't pay AWS to shuffle packets to S3 when they'll do it free.

Cause 3: Security Group Egress Blocking the Endpoint

Less common, but it happens after someone "hardened" the Lambda's security group. The default SG allows all outbound. If yours has been locked down to a specific CIDR, it won't allow traffic to the S3 prefix list.

S3 Gateway Endpoints use a managed prefix list, and traffic to it still needs to be permitted by your egress rules. If your Lambda's SG only allows outbound to 10.0.0.0/8, it can't reach S3's prefix list, which contains public AWS ranges.

Fix: add an outbound rule allowing TCP 443 to the S3 prefix list. Find the list ID:

aws ec2 describe-prefix-lists \
  --filters Name=prefix-list-name,Values=com.amazonaws.us-east-1.s3

Then reference that pl-xxxxxxxx in the outbound rule. Don't hardcode AWS IP ranges — they change, and you'll be debugging this again every three months.

Also check the network ACL on the subnet. NACLs are stateless, so you need both an outbound rule for ephemeral ports and an inbound rule for the return traffic. If someone tightened the NACL to deny all inbound except port 22, your return packets get dropped and you see timeouts. NACLs are the silent killer in VPC networking. Most people never look at them.

Quick reference

CauseHow to spot itFixCost
No S3 Gateway Endpoint All AWS API calls time out; VPC-internal calls work Create Gateway Endpoint, attach to all subnet route tables Free
Lambda in public subnet, no public IP IGW route exists but timeouts persist Move to private subnet + Gateway Endpoint (or add NAT) Free / ~$32/mo
SG egress or NACL blocking Intermittent or after a security hardening change Allow 443 to S3 prefix list; check NACL return rules Free

Start with the Gateway Endpoint. It's the right answer 9 times out of 10, and if it isn't the whole fix, it's at least part of it. Then check route table coverage across every subnet, and only then start poking at security groups.

Related Errors in Server & Cloud
0X0000043B Fix ERROR_SERVICE_NOT_IN_EXE (0X0000043B) Fast Hosting Move Messed Up File Permissions? Here's the Fix 0XC00002FC Fix STATUS_KDC_UNABLE_TO_REFER (0XC00002FC) in Windows Server 0X000013AE Cluster Resource Error 0x000013AE: Quick Fix Guide

Was this solution helpful?

EP
Erropedia Team
Tech Support Editors
The Erropedia editorial team researches and documents real-world tech errors from across Windows, Linux, macOS, networking, databases, cloud platforms, and more. Every solution is reviewed for accuracy and updated as software and systems evolve.