A Story About Encountering a CreateNetworkInterface Permission Error for VPC Lambda in CDK Express Mode
This page has been translated by machine translation. View original
Introduction
Hello, I'm Junkichi.
I encountered the following error related to Lambda with 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, CDK automatically attaches AWSLambdaVPCAccessExecutionRole (a managed policy containing ENI permissions) to the execution role when vpc is specified in lambda.Function, so this permission error should not normally occur.
Conclusion
The cause was that it was being run in Express mode. Because Express considers role updates as immediately complete without waiting for policy propagation (eventual consistency), the ENI creation that runs immediately after triggers an AccessDenied error for CreateNetworkInterface.
The solution is to deploy in standard mode (without skipping 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. It is also supported in CDK and can be used 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, permissions are granted based on whether vpc is configured. The fact that the permissions are being granted could also be confirmed from the template obtained by running synth. This suggests the issue is not with CDK itself, but rather with the eventual consistency of the IAM data plane (propagation delay until a role/policy attachment actually becomes effective). Similar cases have been reported in Issues (aws-cdk#7998).
Verification
Verification was performed with the following setup.
- aws-cdk-lib
2.261.0/ aws-cdk2.1132.0/ Node.js26.5.0 - Region:
ap-northeast-1
For verification, I prepared a CDK stack that can toggle VPC configuration on and off via a context flag. The relevant Lambda excerpt is as follows.
// VpcConfig is only attached 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 in Express mode to convert a non-VPC Lambda to a VPC Lambda. 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 complete without waiting for propagation) |
| 16:02:25 | AWS::Lambda::Function |
UPDATE starts |
| 16:02:27 | AWS::Lambda::Function |
UPDATE_FAILED: No CreateNetworkInterface permission (only 4 seconds after role completion, policy not yet propagated) |
In a non-VPC → VPC UPDATE, "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 the not-yet-propagated VPCAccess, resulting in AccessDenied.
Trying with Standard Mode
Keeping the same configuration but switching only the deployment mode to standard, I ran the same UPDATE. This time it succeeded. The timeline is as follows.
| Time | Resource | Event |
|---|---|---|
| 16:15:34 | AWS::IAM::Role |
UPDATE starts |
| 16:15:50 | AWS::IAM::Role |
UPDATE_COMPLETE (stabilization = approximately 16 seconds waiting for propagation) |
| 16:15:52 | AWS::Lambda::Function |
UPDATE starts |
| 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 runs 4 seconds later collides with the not-yet-propagated policy. Standard, on the other hand, waits approximately 16 seconds for the role update to stabilize (propagate), so the permissions are in place by the time ENI creation runs.
Note: Creation from Scratch Succeeds
As a side note, a fresh CREATE (VPC Lambda from the start) succeeds even in Express mode.
This is because the creation of AWS::Lambda::Function is not short-circuited even in Express mode and takes approximately 2 minutes. During these approximately 2 minutes, the VPCAccess of the role propagates sufficiently, so the permissions are in place when the ENI is created. In fact, even after repeating destroy→create 5 times, the error 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 for Function creation) |
| Express / fresh CREATE (VPC Lambda) | ✅ Success (even in Express, approximately 2-minute wait remains for Lambda::Function only) |
| 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,
CreateNetworkInterfaceis 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.
