2026, Jan 07 13:00

Resolve pydantic_core._pydantic_core ModuleNotFoundError in Dockerized Python by Switching from 3.11 to 3.13

Fix ModuleNotFoundError pydantic_core._pydantic_core in Docker: Python 3.11 breaks pydantic-core. Upgrade uv venv to Python 3.13 to resolve MCP import failures.

Hitting ModuleNotFoundError for pydantic_core._pydantic_core inside a Dockerized environment can be baffling, especially when uv pip freeze confirms that pydantic-core is installed. This guide walks through a reproducible setup on node:20-alpine and shows why the import fails with Python 3.11, what exactly is going on, and how to make it work reliably.

Reproducing the issue

The following container builds a minimal environment with uv, installs mcp, and attempts to import from mcp.server. Even though pydantic-core is present according to the package list, the import blows up.

FROM node:20-alpine

RUN apk add --no-cache curl

RUN curl -LsSf https://astral.sh/uv/install.sh | sh

ENV PATH="/root/.local/bin:${PATH}"

WORKDIR /app

RUN uv venv --python=3.11 && \
    uv pip install mcp

COPY test_mcp.py .

CMD ["uv", "run", "test_mcp.py"]
# test_mcp.py
from mcp.server import NotificationOptions as NotifyOpts, Server as RpcSrv

Running the container results in an error similar to the following:

ModuleNotFoundError: No module named 'pydantic_core._pydantic_core'

At the same time, the environment shows these packages installed:

pydantic==2.11.3
pydantic-core==2.33.1

Notice that the site-packages path in the traceback points to python3.11, which confirms the runtime version used by the virtual environment.

What’s actually going wrong

The failure is not about package presence or location. It’s a Python runtime issue. Python versions lower than 3.13 do not correctly infer the extension suffix for certain compiled libraries such as pydantic-core. As a result, even though the wheel is installed, the runtime can’t resolve the compiled module, and the import fails with ModuleNotFoundError. This behavior is tracked upstream; see python/cpython#95855 for details: https://github.com/modelcontextprotocol/python-sdk/issues/570.

Fixing the problem

The practical fix is to run on Python 3.13 or newer. In the Docker setup above, that boils down to creating the virtual environment with Python 3.13 instead of 3.11. Everything else can remain the same.

FROM node:20-alpine

RUN apk add --no-cache curl

RUN curl -LsSf https://astral.sh/uv/install.sh | sh

ENV PATH="/root/.local/bin:${PATH}"

WORKDIR /app

RUN uv venv --python=3.13 && \
    uv pip install mcp

COPY test_mcp.py .

CMD ["uv", "run", "test_mcp.py"]
# test_mcp.py
from mcp.server import NotificationOptions as NotifyOpts, Server as RpcSrv

With Python 3.13 or later, the runtime correctly handles the compiled extension, and the import succeeds.

Why this matters

Modern Python libraries often ship compiled wheels for performance. If the interpreter can’t resolve the extension module naming convention, you get import-time failures that look like packaging problems but aren’t. In containerized builds, it’s easy to assume you’re on one version while a virtual environment silently pins you to another, which makes the issue harder to spot. Aligning the interpreter version with the expectations of compiled dependencies prevents this entire class of runtime errors.

Takeaways

If you see ModuleNotFoundError for pydantic_core._pydantic_core in a container that otherwise shows pydantic-core installed, verify the actual interpreter used by your virtual environment. Use Python 3.13 or later to ensure proper extension suffix handling and avoid false negatives during imports. Keeping the runtime consistent across your base image, virtual environment, and build steps pays off with predictable, reproducible imports and fewer surprises in CI and production.