Textualize/textual · error · AttributeError
module {__name__!r} has no attribute {name!r}
Error message
module {__name__!r} has no attribute {name!r} What it means
Textual defines a module-level __getattr__ in src/textual/__init__.py solely to lazily resolve __version__ from importlib.metadata. Any other attribute access on the textual module that isn't a real module attribute falls through to this hook and raises AttributeError. This is standard Python behavior for module-level __getattr__ (PEP 562).
Source
Thrown at src/textual/__init__.py:52
if TYPE_CHECKING:
from importlib.metadata import version
from textual.app import App as _App
__version__ = version("textual")
"""The version of Textual."""
else:
def __getattr__(name: str) -> str:
"""Lazily get the version."""
if name == "__version__":
from importlib.metadata import version
return version("textual")
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
class LoggerError(Exception):
"""Raised when the logger failed."""
@rich.repr.auto
class Logger:
"""A [logger class](/guide/devtools/#logging-handler) that logs to the Textual [console](/guide/devtools#console)."""
def __init__(
self,
log_callable: LogCallable | None,
group: LogGroup = LogGroup.INFO,
verbosity: LogVerbosity = LogVerbosity.NORMAL,
app: _App | None = None,
) -> None:
self._log = log_callableView on GitHub (pinned to 06dbeef4bb)
Solutions
- Import the correct symbol explicitly: `from textual.app import App` instead of `textual.App`
- Ensure the submodule is imported: `import textual.app` before using `textual.app`
- Check spelling of the attribute against the textual API docs
- If introspecting the module, guard with getattr(textual, name, None) or try/except AttributeError
Example fix
# before import textual app = textual.App() # AttributeError # after from textual.app import App app = App()
Defensive patterns
Strategy: type-guard
Validate before calling
import textual name = 'foo' has_it = name == '__version__' or hasattr(textual, name)
Type guard
def textual_has(name: str) -> bool:
import textual
return name == '__version__' or hasattr(textual, name) Prevention
- Always import symbols explicitly (from textual.app import App) instead of attribute access on the package
- Run a linter/IDE that flags unresolved attributes
- Guard dynamic access with getattr(textual, name, None)
When it happens
Trigger: Accessing any attribute on the textual module that does not exist, e.g. `textual.something` where `something` is neither an import in __init__.py nor '__version__'. Also triggered by hasattr/getattr fallbacks, mock.patch('textual.foo'), or copy/pickle introspecting module attributes.
Common situations: Typos in attribute names (textual.app vs textual.Application), forgetting to import the submodule first (import textual; textual.app without `import textual.app` on some setups), or tooling that walks all module attributes (autocomplete, sphinx, pickle).
Related errors
- Can't animate attribute {attribute!r} on {obj!r}; attribute
- Don't know how to animate {value!r}; Can only animate <int>,
- Can't encode {datum!r}
- must be bytes
- More data expected
AI-assisted analysis of Textualize/textual@06dbeef4bb (2026-08-27).
Data as JSON: /api/errors/f8f9e68fa99281b2.
Report an issue: GitHub.