{"record":{"id":"c17b46b65949d9d7","repo":"headroomlabs-ai/headroom","slug":"module-name-r-has-no-attribute-name-r-c17b46","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":"headroom/transforms/__init__.py","lineNumber":221,"sourceCode":"    \"CacheAligner\": (\"headroom.transforms.cache_aligner\", \"CacheAligner\"),\n    # HTML extraction (optional dependency - requires trafilatura)\n    \"HTMLExtractor\": (\"headroom.transforms.html_extractor\", \"HTMLExtractor\"),\n    \"HTMLExtractorConfig\": (\"headroom.transforms.html_extractor\", \"HTMLExtractorConfig\"),\n    \"HTMLExtractionResult\": (\"headroom.transforms.html_extractor\", \"HTMLExtractionResult\"),\n    \"is_html_content\": (\"headroom.transforms.html_extractor\", \"is_html_content\"),\n}\n\n\ndef __getattr__(name: str) -> object:\n    if name == \"__path__\":\n        raise AttributeError(name)\n    if name == \"_HTML_EXTRACTOR_AVAILABLE\":\n        return _HTML_EXTRACTOR_AVAILABLE\n\n    try:\n        module_name, attr_name = _LAZY_EXPORTS[name]\n    except KeyError as exc:\n        raise AttributeError(f\"module {__name__!r} has no attribute {name!r}\") from exc\n\n    module = import_module(module_name)\n    value = getattr(module, attr_name)\n    globals()[name] = value\n    return value\n\n\ndef __dir__() -> list[str]:\n    return sorted(set(globals()) | set(__all__))\n","sourceCodeStart":203,"sourceCodeEnd":231,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/headroom/transforms/__init__.py#L203-L231","documentation":"headroom.transforms implements lazy exports via a module-level __getattr__: names listed in _LAZY_EXPORTS are imported on first access so heavy modules (e.g. the HTML extractor) load only when used. Any attribute not in globals(), __all__, or _LAZY_EXPORTS raises AttributeError with the module's __name__ and the missing name — the standard 'no attribute' semantics, just produced by the lazy loader.","triggerScenarios":"from headroom.transforms import StripHTMLTypo; transforms.SomeTransform (name not exported under that spelling); accessing a symbol that lives in a submodule directly (headroom.transforms.html.extract) but was never re-exported in _LAZY_EXPORTS/__all__.","commonSituations":"IDE autocompleting a private helper; names renamed between versions (old imports break); users assuming every symbol in submodules is re-exported at the package root; `import headroom.transforms as t; t.partial` style probing.","solutions":["Check the package __all__/docs for the exact public spelling and use it.","If the symbol genuinely exists in a submodule but is not re-exported, import from the full path: from headroom.transforms.html import extract_x.","On version upgrades, grep the changelog for renames of the transform you use.","Use dir(headroom.transforms) — __dir__ merges globals and __all__ — to see what is addressable."],"exampleFix":"# before\nfrom headroom.transforms import strip_html  # AttributeError: not exported\n\n# after\nimport headroom.transforms as T\nprint([n for n in dir(T) if \"html\" in n.lower()])\nfrom headroom.transforms import HtmlStripTransform  # exact exported name","handlingStrategy":"type-guard","validationCode":"import headroom.transforms as T\nassert \"TargetSymbol\" in dir(T), f\"not exported; available: {[n for n in dir(T)]}\"","typeGuard":"def exports(name: str) -> bool:\n    import headroom.transforms as T\n    return name in dir(T)","tryCatchPattern":"try:\n    from headroom.transforms import TargetSymbol\nexcept AttributeError as e:\n    raise ImportError(f\"{e}; check headroom.transforms.__all__ for the public name\") from e","preventionTips":["Import from explicit submodule paths for symbols not in __all__.","Use dir(module) (it merges __all__) to discover lazy exports.","Pin versions and update imports on rename announcements."],"tags":["imports","lazy-loading","api-misuse","typo"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}