pytest-dev/pytest · error · ImportError

import error in {used}: {ex}

Error message

import error in {used}: {ex}

What it means

`resolve()` walks a dotted import path component by component. When an intermediate or final segment can't be imported as a submodule AND the ImportError's message does not match the segment being imported (meaning the failure is a deeper dependency), it re-raises as `ImportError("import error in <used>: <original>")`. This distinguishes 'this module does not exist' from 'this module exists but one of its imports fails'.

Source

Thrown at src/_pytest/monkeypatch.py:88

    found: object = importlib.import_module(used)
    for part in parts:
        used += "." + part
        try:
            found = getattr(found, part)
        except AttributeError:
            pass
        else:
            continue
        # We use explicit un-nesting of the handling block in order
        # to avoid nested exceptions.
        try:
            importlib.import_module(used)
        except ImportError as ex:
            expected = str(ex).split()[-1]
            if expected == used:
                raise
            else:
                raise ImportError(f"import error in {used}: {ex}") from ex
        found = annotated_getattr(found, part, used)
    return found


def annotated_getattr(obj: object, name: str, ann: str) -> object:
    try:
        obj = getattr(obj, name)
    except AttributeError as e:
        raise AttributeError(
            f"{type(obj).__name__!r} object at {ann} has no attribute {name!r}"
        ) from e
    return obj


def derive_importpath(import_path: str, raising: bool) -> tuple[str, object]:
    if not isinstance(import_path, str) or "." not in import_path:
        raise TypeError(f"must be absolute import path string, not {import_path!r}")
    module, attr = import_path.rsplit(".", 1)

View on GitHub (pinned to 98b357f69e)

Solutions

  1. Import the target module in a Python REPL first (`import pkg.mod`) to surface the real ImportError.
  2. Fix or install the missing dependency of the target module.
  3. Verify the dotted path spelling — a wrong segment sends resolve down the wrong submodule chain.

Example fix

# before
monkeypatch.setattr('mypkg.svc.client', fake)  # mypkg.svc import fails due to missing dep
# after
# fix the import in mypkg.svc (install missing dep), then:
monkeypatch.setattr('mypkg.svc.client', fake)
Defensive patterns

Strategy: validation

Validate before calling

import importlib
def module_imports_cleanly(dotted: str) -> bool:
    module = dotted.rsplit('.', 1)[0]
    try:
        importlib.import_module(module)
    except ImportError:
        return False
    return True

Try / catch

try:
    monkeypatch.setattr('pkg.mod.attr', fake)
except ImportError as e:
    # fix the underlying import, then retry
    ...

Prevention

When it happens

Trigger: `monkeypatch.setattr('pkg.mod.attr', ...)` where `pkg.mod` imports a missing/broken dependency; or `derive_importpath` on a path whose submodule raises ImportError during import.

Common situations: Patching an attribute in a module that itself fails to import (missing optional dep, broken symlink, version mismatch); circular imports; patched path typed wrong so pytest tries the wrong submodule chain.

Related errors


AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04). Data as JSON: /data/errors/5d856b5b5869b0d4.json. Report an issue: GitHub.