{"record":{"id":"5d856b5b5869b0d4","repo":"pytest-dev/pytest","slug":"import-error-in-used-ex","errorCode":null,"errorMessage":"import error in {used}: {ex}","messagePattern":"import error in (.+?): (.+?)","errorType":"exception","errorClass":"ImportError","httpStatus":null,"severity":"error","filePath":"src/_pytest/monkeypatch.py","lineNumber":88,"sourceCode":"    found: object = importlib.import_module(used)\n    for part in parts:\n        used += \".\" + part\n        try:\n            found = getattr(found, part)\n        except AttributeError:\n            pass\n        else:\n            continue\n        # We use explicit un-nesting of the handling block in order\n        # to avoid nested exceptions.\n        try:\n            importlib.import_module(used)\n        except ImportError as ex:\n            expected = str(ex).split()[-1]\n            if expected == used:\n                raise\n            else:\n                raise ImportError(f\"import error in {used}: {ex}\") from ex\n        found = annotated_getattr(found, part, used)\n    return found\n\n\ndef annotated_getattr(obj: object, name: str, ann: str) -> object:\n    try:\n        obj = getattr(obj, name)\n    except AttributeError as e:\n        raise AttributeError(\n            f\"{type(obj).__name__!r} object at {ann} has no attribute {name!r}\"\n        ) from e\n    return obj\n\n\ndef derive_importpath(import_path: str, raising: bool) -> tuple[str, object]:\n    if not isinstance(import_path, str) or \".\" not in import_path:\n        raise TypeError(f\"must be absolute import path string, not {import_path!r}\")\n    module, attr = import_path.rsplit(\".\", 1)","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/pytest-dev/pytest/blob/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/monkeypatch.py#L70-L106","documentation":"An ImportError raised by _pytest.monkeypatch when resolving a dotted import path and an intermediate module fails to import, but the failure is for a different module than the one being imported (a transitive import error). The original exception is chained; the message wraps the inner error with the failing segment name so the user knows which part of the dotted path broke.","triggerScenarios":"Calling `monkeypatch.setattr('a.b.c', value)` or `monkeypatch.delattr('a.b.c')` where importing `a` or `a.b` raises an ImportError whose offending module is not the segment being imported. For example, `a` imports fine but triggers an ImportError from a sibling module.","commonSituations":"Patching a path in a package whose __init__ has conditional imports; missing optional dependencies of an intermediate package; circular imports; wrong environment where a transitive dependency is absent.","solutions":["Read the chained ImportError: the inner message names the truly missing module.","Install the missing dependency or fix the intermediate package's __init__.","Verify the dotted path resolves in a plain Python session: `python -c 'import a.b.c'`.","Patch a more specific path (closer to the leaf) to avoid importing a heavy/buggy intermediate."],"exampleFix":"# before\nmonkeypatch.setattr('mypkg.sub.target', new_val)\n# ImportError: import error in mypkg.sub: No module named 'missing_dep'\n# after\n# (install missing_dep, or patch where target already lives)\nimport mypkg.sub.target as t\nmonkeypatch.setattr(t, 'attr', new_val)","handlingStrategy":"try-catch","validationCode":"import importlib\ndef path_resolves(dotted: str) -> bool:\n    parts = dotted.split('.')\n    mod = parts[0]\n    try:\n        obj = importlib.import_module(mod)\n    except ImportError:\n        return False\n    for p in parts[1:]:\n        if not hasattr(obj, p):\n            return False\n        obj = getattr(obj, p)\n    return True","typeGuard":null,"tryCatchPattern":"try:\n    monkeypatch.setattr('a.b.c', value)\nexcept ImportError as e:\n    # inspect chained exception for the truly missing module\n    print(f'transitive import failed: {e.__cause__}')","preventionTips":["Verify the dotted path imports in plain Python first.","Install all transitive dependencies of the target package.","Patch a more specific leaf to avoid heavy intermediate imports."],"tags":["pytest","monkeypatch","import-error","import-path","fixtures"],"backgroundTag":null,"analyzedSha":"0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc","analyzedAt":"2026-08-11T20:52:36.969Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}