ModuleNotFoundError: No module named 'requests'

Short answer

Python could not find a module on its import path while loading your handler. On Lambda that path is /var/task (your package) plus /opt/python (your layers) plus the standard library — nothing else, and in particular nothing from the machine you developed on.

What it means

Python resolves imports by walking sys.path, and inside a Lambda execution environment that path is much shorter than the one you develop against. It contains /var/task, where your deployment package is extracted; /opt/python, where layers land; and the standard library that ships with the runtime. Your virtualenv is not there. Neither is anything pip installed globally on the build machine, nor anything reachable through a PYTHONPATH you set in a shell.

The import runs during init, while the runtime is loading your handler module, so the failure lands before your code executes and before there is an event to process. That is why you see no output of your own — not even a print at the top of the file — and why every invocation fails identically rather than intermittently.

Two structural details cause most real occurrences. The first is platform: any package with compiled components is distributed as platform-specific wheels, and a wheel installed on macOS or Apple Silicon is not loadable on an x86_64 Linux Lambda. Pip installs the wheel matching the machine it is running on unless told otherwise, so a build that works perfectly on a laptop produces an artifact that cannot import in production. The second is layer layout: a layer is extracted to /opt, but only /opt/python is on the import path, so a layer built without a top-level python/ directory attaches successfully, reports no error, and contributes nothing.

There is a third case worth separating out, because it looks the same and is not. When the message reads Unable to import module 'lambda_function', the module Lambda could not find is yours. The handler configuration is a dotted path of the form file.function with no .py extension, and if the file sits inside a directory in the zip, that directory belongs in the handler string too. Nothing is missing from the package in that case — Lambda is simply looking in the wrong place.

Counts

CloudWatch’s Errors metric: The error escaped your handler, so Lambda reports the invocation as failed and CloudWatch’s Errors metric counts it. LogStitch classified the invocation above as uncaught.

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

6 raw lines, in the order CloudWatch delivered them.

2026-08-29T06:55:19.204Z INIT_START Runtime Version: python:3.12.v41 Runtime Version ARN: arn:aws:lambda:us-east-1::runtime:9b1f5a2c
2026-08-29T06:55:19.388Z [ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_function': No module named 'requests'
2026-08-29T06:55:19.388Z Traceback (most recent call last):
2026-08-29T06:55:19.501Z START RequestId: 4a91e7b3-0c62-4d8f-91ae-3b7d2f5c8e10 Version: $LATEST
2026-08-29T06:55:19.503Z END RequestId: 4a91e7b3-0c62-4d8f-91ae-3b7d2f5c8e10
2026-08-29T06:55:19.503Z REPORT RequestId: 4a91e7b3-0c62-4d8f-91ae-3b7d2f5c8e10 Duration: 2.11 ms Billed Duration: 3 ms Memory Size: 256 MB Max Memory Used: 62 MB Init Duration: 184.22 ms Status: error Error Type: Runtime.ImportModuleError

LogStitch After

The same lines, grouped into the invocation they belong to.

ErrorCold start · 184ms init4a91e7b3-0c62-4d8f-91ae-3b7d2f5c8e10dur 2.11msbilled 3.00msmem 62/256MBlogs 6
  1. 06:55:19.204PLAT
    INIT_START Runtime Version: python:3.12.v41 Runtime Version ARN: arn:aws:lambda:us-east-1::runtime:9b1f5a2c
  2. 06:55:19.388ERROR
    [ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_function': No module named 'requests'
  3. 06:55:19.388
    Traceback (most recent call last):
  4. 06:55:19.501PLAT
    START RequestId: 4a91e7b3-0c62-4d8f-91ae-3b7d2f5c8e10 Version: $LATEST
  5. 06:55:19.503PLAT
    END RequestId: 4a91e7b3-0c62-4d8f-91ae-3b7d2f5c8e10
  6. 06:55:19.503PLAT
    REPORT RequestId: 4a91e7b3-0c62-4d8f-91ae-3b7d2f5c8e10	Duration: 2.11 ms	Billed Duration: 3 ms	Memory Size: 256 MB	Max Memory Used: 62 MB	Init Duration: 184.22 ms	Status: error	Error Type: Runtime.ImportModuleError
Error
Status
2.11ms
Duration
3.00ms
Billed
62/256MB
Memory
76%
Headroom
Yes
Cold start
Runtime.ImportModuleError
Error type

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 line appears before any of your own logging, immediately after INIT_START, because the import runs while the handler module is being loaded. The Python runtime writes it as [ERROR] Runtime.ImportModuleError: Unable to import module '<your_handler>': No module named '<package>', followed by a Traceback block. The handler module named in the first half is yours; the package named in the second half is the one that could not be found.

If the traceback shows the failure inside a package rather than in your own file, the missing module is a transitive dependency — something you installed depends on something that was not installed with it.

Causes, most likely first

1

The dependency was never packaged, only pip-installed locally

How to confirm

Unzip the artifact and look for the package directory at the top level. Lambda's Python runtime does not read your virtualenv, your requirements.txt, or anything on the build machine — only what is inside the zip and any attached layers. A requirements.txt that lists the package proves nothing about what shipped.

2

The package was built on the wrong platform

How to confirm

Check whether the package has compiled components — pandas, numpy, psycopg2, cryptography, pydantic and anything wrapping a C library all do. A wheel installed on macOS or on Apple Silicon will not import on an x86_64 Linux Lambda, and the symptom is frequently a plain "no module named" rather than an architecture complaint.

3

A layer is attached but its contents are at the wrong path

How to confirm

Layers are extracted to /opt, and the Python runtime only adds /opt/python and /opt/python/lib/python3.x/site-packages to the import path. A layer zipped with the packages at its root puts them at /opt/requests, which is not on the path. Check the layer's internal directory structure, not just that it is attached.

4

The handler module itself cannot be found

How to confirm

Read the module name in the first half of the message. Unable to import module 'lambda_function' means Lambda could not find your entry file, not a dependency — check the configured handler string against the filename in the zip, remembering it is file.function with no .py extension.

5

The name imported differs from the name installed

How to confirm

Compare the import statement with the distribution name. Many packages install under a different name than they are published as — pip install python-dateutil provides dateutil, pip install PyYAML provides yaml. Installing the import name instead of the distribution name silently installs nothing useful.

Fixes

Fix 1

Install into the package directory, targeting Lambda's platform

Build the dependencies for the runtime rather than for your machine. --platform with --only-binary=:all: forces pip to fetch Linux wheels instead of building for the local one, which is what makes compiled packages work.

bashpip install \
  --target ./package \
  --platform manylinux2014_x86_64 \
  --implementation cp \
  --python-version 3.12 \
  --only-binary=:all: \
  -r requirements.txt

cd package && zip -qr ../function.zip . && cd ..
zip -q function.zip lambda_function.py
Fix 2

Structure a layer so the runtime can actually see it

A layer's contents land under /opt, and only /opt/python is on the Python import path. The packages must therefore sit inside a top-level python/ directory in the layer zip — this is the single most common reason an attached layer appears to do nothing.

bash# Correct layer layout:
#   python/requests/...
#   python/urllib3/...
mkdir -p python
pip install -r requirements.txt --target python/
zip -qr layer.zip python/
Fix 3

Build in a container that matches the runtime

For anything with compiled dependencies, the reliable answer is to build where you run. The public AWS base images are the same environment your function executes in, so a wheel that installs there will import in production.

bashdocker run --rm --platform linux/amd64 \
  -v "$PWD":/var/task \
  public.ecr.aws/lambda/python:3.12 \
  pip install -r requirements.txt --target /var/task/package

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.

[ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_function': No module named 'requests'ImportError: cannot import name 'X' from 'Y'No module named 'pandas'No module named 'psycopg2'lambda python import error

Errors that show up alongside this one, or that people mistake for it.

References

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.