What it means
Attaching an EFS file system to a Lambda gives it something the execution environment otherwise lacks: storage that persists between invocations and is shared across every concurrent execution. It is how functions handle working sets larger than /tmp, share model files, or write output that outlives the request.
The cost is that the mount becomes part of initialisation. Before your handler is invoked, Lambda attaches the network interface, reaches the mount target over NFS, and mounts the access point. All three have to succeed, and if any fails the invocation fails before your code exists. That is why the logs are so empty: there is no stack trace, no line of your own output, just the platform reporting that it could not get the file system ready.
The four exceptions map onto stages of that sequence, and reading which one you got is most of the diagnosis. Connectivity failures mean the NFS traffic never arrived — nearly always a security group that does not allow TCP 2049 from the function, or a function running in an availability zone with no mount target. Mount failures mean the target was reached and refused, which is the access point and its permissions. Timeouts mean the operation was still going when it was abandoned. And EFSIOException is not a mount problem at all — the file system was attached successfully and an operation on it failed later, which usually means POSIX ownership on the access point does not match what the code is trying to do.
The availability-zone case deserves particular attention because of how it presents. Lambda spreads execution environments across the subnets you configure. If mount targets exist in two of three AZs, roughly a third of your cold starts land somewhere with nothing to mount and fail, while the rest work perfectly. The function looks intermittently broken at a stable rate, and nothing about one failing invocation explains why the one before it succeeded.
CloudWatch’s Errors metric: The error escaped your handler, so Lambda reports the invocation as failed and CloudWatch’s Errors metric counts it. The mount happens before your handler runs, so a failure fails the invocation and CloudWatch counts it. LogStitch classified the example below from its log level rather than an extracted error type, because the message arrives as a plain error line.
What it looks like in CloudWatch
This is the shape the failure arrives in: the lines of one invocation scattered among everything else the log group received at the same moment.
CloudWatch Logs Before
5 raw lines, in the order CloudWatch delivered them.
LogStitch After
The same lines, grouped into the invocation they belong to.
ErrorCold start · 394ms initd81a3c60-4f27-4b95-a013-2e6b8f0c7d94
- 12:05:41.008PLAT
INIT_START Runtime Version: python:3.12.v41 Runtime Version ARN: arn:aws:lambda:us-east-1::runtime:9b1f5a2c
- 12:05:41.402
EFSMountFailureException: The function could not mount the Amazon EFS file system fs-0a1b2c3d4e5f67890 with access point fsap-0123456789abcdef0
- 12:05:41.511PLAT
START RequestId: d81a3c60-4f27-4b95-a013-2e6b8f0c7d94 Version: $LATEST
- 12:05:41.514PLAT
END RequestId: d81a3c60-4f27-4b95-a013-2e6b8f0c7d94
- 12:05:41.514PLAT
REPORT RequestId: d81a3c60-4f27-4b95-a013-2e6b8f0c7d94 Duration: 3.11 ms Billed Duration: 4 ms Memory Size: 1024 MB Max Memory Used: 74 MB Init Duration: 394.22 ms Status: error
The panel on the right is generated by running the excerpt on the left through the same parser that powers the free web stitcher — it is what the tool actually produces for this input, not an illustration of it.
How to confirm it from the logs
The four EFS exceptions describe different stages of the same operation, and which one you get narrows the cause sharply. EFSMountConnectivityException means the function could not reach the mount target at all — a routing or security-group problem. EFSMountFailureException means it reached it and the mount was refused, which points at the access point or its permissions. EFSMountTimeoutException means the mount was still in progress when the attempt gave up. EFSIOException is different again: the mount succeeded and a later read or write failed.
Check the position relative to START. A mount failure precedes any of your own output, because the file system is attached before the handler is invoked.
Causes, most likely first
The function's security group cannot reach the mount target on NFS
Check that the mount target's security group allows inbound TCP 2049 from the function's security group. This is the most common cause and surfaces as EFSMountConnectivityException — the packets never arrive, so the mount never begins.
The function and the mount targets are in different availability zones
Compare the subnets configured on the function against the subnets that have EFS mount targets. A function scheduled into an AZ with no mount target has nothing local to reach, and the behaviour looks intermittent because only some execution environments land there.
The execution role lacks the EFS client permissions
Check the role for elasticfilesystem:ClientMount and, for writes, ClientWrite. The file system policy must also permit the role — like KMS, EFS evaluates both sides, so an identity policy alone can be insufficient.
The access point's POSIX ownership does not match what the function writes as
Look at the access point's PosixUser and root directory CreationInfo. If the owner UID and GID do not match the access point's enforced identity, the mount can succeed and every write then fail with a permission error — which surfaces as EFSIOException rather than a mount failure.
The function is not in a VPC, or is in the wrong one
EFS is reachable only from within a VPC. Confirm the function has a VPC configuration and that it is the VPC the file system's mount targets live in.
Fixes
Allow NFS from the function's security group to the mount target
The mount target must accept TCP 2049 from the function. Referencing the function's security group by id, rather than a CIDR, keeps the rule correct as subnets change.
yamlMountTargetIngress:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !Ref EfsSecurityGroup
IpProtocol: tcp
FromPort: 2049
ToPort: 2049
SourceSecurityGroupId: !Ref LambdaSecurityGroup
Grant the execution role EFS client access, on both sides
EFS checks the identity policy and the file system policy. Granting only the first leaves the mount refused with no indication that the file system policy is what declined it.
yaml- Effect: Allow
Action:
- elasticfilesystem:ClientMount
- elasticfilesystem:ClientWrite
- elasticfilesystem:DescribeMountTargets
Resource: !GetAtt FileSystem.Arn
Put mount targets in every AZ the function can run in
Lambda places execution environments across the subnets you give it. Every one of those AZs needs a mount target, or invocations landing in the others fail while the rest succeed — which reads as random and is not.
bashaws efs describe-mount-targets --file-system-id fs-0abc \
--query 'MountTargets[].{AZ:AvailabilityZoneName,Subnet:SubnetId,State:LifeCycleState}'
Match the access point's POSIX identity to what your code expects
An access point enforces a UID and GID on every operation regardless of what the process thinks it is. Set the root directory's ownership to the same identity, or writes fail after a mount that appeared to succeed.
yamlAccessPoint:
Type: AWS::EFS::AccessPoint
Properties:
FileSystemId: !Ref FileSystem
PosixUser:
Uid: "1000"
Gid: "1000"
RootDirectory:
Path: /lambda
CreationInfo:
OwnerUid: "1000"
OwnerGid: "1000"
Permissions: "0755"
Also seen as
The same underlying failure, worded differently by a different runtime, SDK version, or logging layer. All of these land here — there is no separate page for each phrasing.
Related errors
Errors that show up alongside this one, or that people mistake for it.
References
- AWS Lambda Developer Guide — Configuring file system access for Lambda functions
- Amazon EFS User Guide — Working with access points
LogStitch finds this automatically, across every invocation in your account.
Paste a log excerpt into the free web stitcher and see it grouped, classified, and measured in your browser — nothing is uploaded. Or run the Mac app against your own AWS profiles and get the same view over every function you own.