A Story About Encountering a CreateNetworkInterface Permission Error in CDK VPC Lambda

A Story About Encountering a CreateNetworkInterface Permission Error in CDK VPC Lambda

When I put Lambda in a VPC with CDK, I got a CreateNetworkInterface permission error. CDK should automatically grant the necessary permissions, so I'll investigate and narrow down the cause through testing.
2026.07.21

This page has been translated by machine translation. View original

Introduction

Hello, I'm Junkichi.

I encountered the following error related to Lambda in AWS CDK.

The provided execution role does not have permissions to
call CreateNetworkInterface on EC2 (Lambda, 400)

VPC Lambda needs to create ENIs (Elastic Network Interfaces), so the execution role requires permissions such as ec2:CreateNetworkInterface. However, when you specify vpc in lambda.Function with CDK, it automatically attaches AWSLambdaVPCAccessExecutionRole (a managed policy that includes ENI permissions) to the execution role, so this permission error should not normally occur.

Conclusion

The cause was that it was running in Express mode. Because Express marks role updates as immediately complete without waiting for policy propagation (eventual consistency), the ENI creation that runs immediately after results in an AccessDenied for CreateNetworkInterface.

The solution is to deploy in standard mode (do not skip stabilization = propagation waiting).

What is Express Mode

Express mode is a CloudFormation feature that speeds up deployments by skipping stack stabilization and eventual consistency checks. CDK also supports it and you can use it with the --express flag.

Reference: CloudFormation Express mode

Checking the CDK Implementation

The location in CDK where VPCAccess is granted is here (aws-cdk-lib/aws-lambda/lib/function.ts).

if (props.vpc) {
  // Policy that will have ENI creation permissions
  managedPolicies.push(iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaVPCAccessExecutionRole'));
}

As expected, it seems to grant permissions based on whether vpc is configured. The fact that permissions are granted could also be confirmed from the template obtained by running synth. This suggests the issue is not with CDK but rather with the IAM data plane's eventual consistency (propagation delay until a role/policy attachment actually takes effect). Similar incidents have also been reported in Issues (aws-cdk#7998).

Verification

Verification was performed with the following environment.

  • aws-cdk-lib 2.261.0 / aws-cdk 2.1132.0 / Node.js 26.5.0
  • Region: ap-northeast-1

I prepared a CDK stack for verification where VPC configuration can be toggled with a context flag. The excerpt of the Lambda portion is as follows.

// VpcConfig is only applied when vpcMode='on'.
// By deploying with vpc=off and then updating to vpc=on, we can reproduce a "non-VPC → VPC" update.
const vpcProps =
  vpcMode === 'on'
    ? { vpc, vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED } }
    : {};
const fn = new lambda.Function(this, 'Fn', {
  runtime: lambda.Runtime.NODEJS_22_X,
  handler: 'index.handler',
  code: lambda.Code.fromInline("exports.handler = async () => ({ statusCode: 200, body: 'ok' });"),
  timeout: Duration.seconds(10),
  ...vpcProps,
});

Reproducing the Issue in Express Mode

Using the same configuration (auto-generated role), I ran an UPDATE with Express to convert a non-VPC Lambda to VPC. The same error as the user's case was reproduced. The timeline of events is as follows.

Time Resource Event
16:02:23 AWS::IAM::Role UPDATE_COMPLETE — "completed using Express Mode. It may continue becoming available in the background" (VPCAccess addition marked as complete without waiting for propagation)
16:02:25 AWS::Lambda::Function UPDATE started
16:02:27 AWS::Lambda::Function UPDATE_FAILED: No CreateNetworkInterface permission (only 4 seconds after role completion, policy not yet propagated)

In an UPDATE from non-VPC → VPC, "adding VPCAccess to the existing role" and "adding VpcConfig to the function (= ENI creation)" run consecutively within the same update. Because Express marks the role update as complete without waiting for propagation, the ENI creation during the function update a few seconds later runs against VPCAccess that has not yet propagated, resulting in AccessDenied.

Trying with Standard Mode

Keeping the same configuration and only changing the deployment mode to standard, I ran the same UPDATE. This time it succeeds. The timeline is as follows.

Time Resource Event
16:15:34 AWS::IAM::Role UPDATE started
16:15:50 AWS::IAM::Role UPDATE_COMPLETE (stabilization = approximately 16 seconds waiting for propagation)
16:15:52 AWS::Lambda::Function UPDATE started
16:17:57 AWS::Lambda::Function UPDATE_COMPLETE (ENI creation succeeded, approximately 2 minutes)

The decisive difference between Express and standard is the time it takes for the role update to complete. Express marks the role update as complete in about 1 second, and the ENI creation that ran 4 seconds later collided with the unpropagated policy. Standard, on the other hand, waits about 16 seconds for the role update to stabilize (propagate), so the subsequent ENI creation passes the permission check.

Note: Creation from Scratch Succeeds

As a side note, a CREATE from scratch (VPC Lambda from the beginning) also succeeds even in Express mode.

This is because the creation of AWS::Lambda::Function is not short-circuited even in Express mode and takes about 2 minutes. During these approximately 2 minutes, the VPCAccess of the role propagates sufficiently, so permissions pass at the time of ENI creation. In fact, after repeating destroy → create 5 times, the issue was never reproduced during CREATE.

Verification Results Summary

The results are summarized as follows.

Configuration Result
standard / fresh CREATE (VPC Lambda) ✅ Success (propagation absorbed by approximately 2 minutes of Function creation)
Express / fresh CREATE (VPC Lambda) ✅ Success (even with Express, Lambda::Function alone retains approximately 2 minutes of waiting)
standard / UPDATE non-VPC→VPC ✅ Success (role update takes approximately 16 seconds = propagation wait)
Express / UPDATE non-VPC→VPC ❌ CreateNetworkInterface error reproduced

Summary

  • When updating a non-VPC Lambda to a VPC Lambda in Express mode, CreateNetworkInterface is executed before IAM propagates, resulting in a permission error.
  • The workaround is to deploy in standard mode, or to delete the Lambda once and then recreate it as a VPC Lambda.

I hope this is helpful to someone.

Share this article