{"record":{"id":"ed91f21e62d685ab","repo":"SeleniumHQ/selenium","slug":"module-name-r-has-no-attribute-name-r","errorCode":null,"errorMessage":"module {__name__!r} has no attribute {name!r}","messagePattern":"module (.+?) has no attribute (.+?)","errorType":"exception","errorClass":"AttributeError","httpStatus":null,"severity":"error","filePath":"py/selenium/webdriver/chrome/__init__.py","lineNumber":28,"sourceCode":"#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\n\nimport importlib\n\n_LAZY_SUBMODULES = [\"options\", \"remote_connection\", \"service\", \"webdriver\"]\n\n\ndef __getattr__(name):\n    if name in _LAZY_SUBMODULES:\n        module = importlib.import_module(f\".{name}\", __name__)\n        globals()[name] = module\n        return module\n    raise AttributeError(f\"module {__name__!r} has no attribute {name!r}\")\n\n\ndef __dir__():\n    return sorted(_LAZY_SUBMODULES)\n","sourceCodeStart":10,"sourceCodeEnd":33,"githubUrl":"https://github.com/SeleniumHQ/selenium/blob/aa36b38e696a0909e973bdf5e2f9031ffe842c4b/py/selenium/webdriver/chrome/__init__.py#L10-L33","documentation":"Selenium uses lazy submodule loading for `selenium.webdriver.chrome` via a module-level `__getattr__`. When you access an attribute on the package, it is only resolved if it is one of the registered lazy submodules (options, remote_connection, service, webdriver). Accessing any other name triggers Python's default missing-attribute behavior through this AttributeError. This is the standard mechanism Python uses to defer expensive imports and to report that a requested name simply does not exist on the package.","triggerScenarios":"Accessing an attribute on `selenium.webdriver.chrome` that is not in the `_LAZY_SUBMODULES` list, e.g. `selenium.webdriver.chrome.Options` (capital O), `selenium.webdriver.chrome.By`, or a misspelled name like `selenium.webdriver.chrome.webrdiver`. Also triggered by `getattr(selenium.webdriver.chrome, \"nonexistent\")`.","commonSituations":"Importing the class wrong: expecting `from selenium import webdriver; webdriver.chrome.Options` to work when it should be `webdriver.ChromeOptions` or `from selenium.webdriver.chrome.options import Options`. Typos after IDE auto-complete. Code written against an older/newer Selenium version where a submodule was renamed or moved. Attempting to reach a remote-only helper from the package root.","solutions":["Import the class directly from its submodule: `from selenium.webdriver.chrome.options import Options`.","If you only need the WebDriver: use `from selenium.webdriver import Chrome` (re-exported at the top level).","Check the spelling against the four valid submodules: options, remote_connection, service, webdriver.","Run `dir(selenium.webdriver.chrome)` to see the valid lazy names."],"exampleFix":"// before\nimport selenium.webdriver.chrome as chrome\nclass Opts(chrome.Options):  # AttributeError\n...\n// after\nfrom selenium.webdriver.chrome.options import Options\nclass Opts(Options):\n    ...","handlingStrategy":"validation","validationCode":"import selenium.webdriver.chrome as chrome\n_VALID = {\"options\", \"remote_connection\", \"service\", \"webdriver\"}\nname = \"options\"\nassert name in _VALID, f\"not a lazy submodule of selenium.webdriver.chrome: {name}\noptions = importlib.import_module(f\"selenium.webdriver.chrome.{name}\")","typeGuard":"def is_lazy_chrome_submodule(name: str) -> bool:\n    return name in {\"options\", \"remote_connection\", \"service\", \"webdriver\"}","tryCatchPattern":"try:\n    from selenium.webdriver.chrome.options import Options\nexcept AttributeError as e:\n    raise ImportError(f\"do not access submodules via the package; import directly: {e}\") from e","preventionTips":["Always import classes from their submodule path, never via the package attribute.","Use `from selenium import webdriver` and `webdriver.Chrome` for the common case.","Run `dir(selenium.webdriver.chrome)` to list valid lazy names before dynamic access."],"tags":["import","lazy-loading","attribute-access","python"],"backgroundTag":null,"analyzedSha":"aa36b38e696a0909e973bdf5e2f9031ffe842c4b","analyzedAt":"2026-08-14T02:32:32.244Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}