{"record":{"id":"527cfd04e938e1e0","repo":"pulumi/pulumi","slug":"module-object-for-original-name-r-substituted-in","errorCode":null,"errorMessage":"module object for {original_name!r} substituted in sys.modules during a lazy load","messagePattern":"module object for (.+?) substituted in sys\\.modules during a lazy load","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdk/python/lib/pulumi/_utils.py","lineNumber":323,"sourceCode":"        original_name = self.__spec__.name\n        # Figure out exactly what attributes were mutated between the creation\n        # of the module and now.\n        attrs_then = self.__spec__.loader_state[\"__dict__\"]\n        attrs_now = self.__dict__\n        attrs_updated = {}\n        for key, value in attrs_now.items():\n            # Code that set the attribute may have kept a reference to the\n            # assigned object, making identity more important than equality.\n            if key not in attrs_then:\n                attrs_updated[key] = value\n            elif id(attrs_now[key]) != id(attrs_then[key]):\n                attrs_updated[key] = value\n        self.__spec__.loader.exec_module(self)\n        # If exec_module() was used directly there is no guarantee the module\n        # object was put into sys.modules.\n        if original_name in sys.modules:\n            if id(self) != id(sys.modules[original_name]):\n                raise ValueError(\n                    f\"module object for {original_name!r} \"\n                    \"substituted in sys.modules during a lazy \"\n                    \"load\"\n                )\n        # Update after loading since that's what would happen in an eager\n        # loading situation.\n        self.__dict__.update(attrs_updated)\n        return getattr(self, attr)\n\n    def __delattr__(self, attr):\n        \"\"\"Trigger the load and then perform the deletion.\"\"\"\n        # To trigger the load and raise an exception if the attribute\n        # doesn't exist.\n        self.__getattribute__(attr)\n        delattr(self, attr)\n\n\nclass _LazyLoader(importlib.abc.Loader):","sourceCodeStart":305,"sourceCodeEnd":341,"githubUrl":"https://github.com/pulumi/pulumi/blob/793f7b2e160db4321fb7fb6b0607461e01cb251e/sdk/python/lib/pulumi/_utils.py#L305-L341","documentation":"Pulumi's `_LazyLoader` (used by `lazy_import`) defers module execution until first attribute access, then verifies the freshly executed module is still the object registered in `sys.modules`. This ValueError fires when, during that lazy load, a different module object was substituted under the same name in `sys.modules` — meaning some hook or custom loader replaced the module, which would leave references inconsistent.","triggerScenarios":"During a lazy load, `exec_module()` (or module code itself) installs a new module object into `sys.modules[original_name]` — e.g. the module re-imports itself, a test double replaces it, or a custom importer hooks `sys.modules` writes.","commonSituations":"Test suites injecting mocks into sys.modules while lazy imports are pending; modules that call `sys.modules[__name__] = something` at import time; circular imports combined with lazy_import; custom meta-path importers fighting the lazy loader.","solutions":["Remove any code that assigns a different object to `sys.modules[<name>]` during import.","Access the module normally (`import module`) instead of through `lazy_import` when mocking is involved.","In tests, mock attributes on the real module after import rather than replacing the module object in sys.modules.","Ensure no custom meta_path finder/loader re-registers the module during exec."],"exampleFix":"// before\n# in module under lazy import\nimport sys\nsys.modules[__name__] = MyShim()\n\n// after\n# in module under lazy import\n# no sys.modules reassignment; expose shim as an attribute\nshim = MyShim()","handlingStrategy":"try-catch","validationCode":"# before lazy load, ensure nothing will replace the module\nassert original_name not in sys.modules or id(sys.modules[original_name]) == id(expected_module)","typeGuard":null,"tryCatchPattern":"try:\n    mod = lazy_import(\"mymodule\")\n    mod.attr\nexcept ValueError as e:\n    if \"substituted in sys.modules\" in str(e):\n        import importlib\n        mod = importlib.import_module(\"mymodule\")\n    else:\n        raise","preventionTips":["Never assign to sys.modules[__name__] inside imported modules.","Mock attributes, not module objects, in tests.","Avoid combining custom meta-path importers with lazy_import."],"tags":["python","import","lazy-load","sys-modules","loader"],"backgroundTag":"lazy-module-load-conflict","analyzedSha":"793f7b2e160db4321fb7fb6b0607461e01cb251e","analyzedAt":"2026-08-31T09:36:43.099Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}