Textualize/textual · error · InvalidPlaceholderVariant
Valid placeholder variants are {friendly_list(_VALID_PLACEHO
Error message
Valid placeholder variants are {friendly_list(_VALID_PLACEHOLDER_VARIANTS)} What it means
Raised by Placeholder.validate_variant when the variant reactive is set to a string not in _VALID_PLACEHOLDER_VARIANTS (e.g. 'default', 'cross', 'size', 'text-widgets', etc.). Because it is a reactive validator it triggers on __init__ or assignment to placeholder.variant.
Source
Thrown at src/textual/widgets/_placeholder.py:172
def cycle_variant(self) -> Self:
"""Get the next variant in the cycle.
Returns:
The `Placeholder` instance.
"""
self.variant = next(self._variants_cycle)
return self
def watch_variant(
self, old_variant: PlaceholderVariant, variant: PlaceholderVariant
) -> None:
self.remove_class(f"-{old_variant}")
self.add_class(f"-{variant}")
def validate_variant(self, variant: PlaceholderVariant) -> PlaceholderVariant:
"""Validate the variant to which the placeholder was set."""
if variant not in _VALID_PLACEHOLDER_VARIANTS:
raise InvalidPlaceholderVariant(
"Valid placeholder variants are "
+ f"{friendly_list(_VALID_PLACEHOLDER_VARIANTS)}"
)
return variant
async def _on_click(self, _: events.Click) -> None:
"""Click handler to cycle through the placeholder variants."""
self.cycle_variant()
def _on_resize(self, event: events.Resize) -> None:
"""Update the placeholder "size" variant with the new placeholder size."""
self._renderables["size"] = self._SIZE_RENDER_TEMPLATE.format(*event.size)
if self.variant == "size":
self.refresh()
View on GitHub (pinned to 06dbeef4bb)
Solutions
- Use one of the documented variants: check _VALID_PLACEHOLDER_VARIANTS in textual/widgets/_placeholder.py for the exact set.
- Pass no variant to use the default.
- Fix typos like 'textwidget' vs 'text-widgets'.
Example fix
# before Placeholder(variant='textwidget') # after Placeholder(variant='text-widgets')
Defensive patterns
Strategy: type-guard
Validate before calling
from textual.widgets._placeholder import _VALID_PLACEHOLDER_VARIANTS
if variant not in _VALID_PLACEHOLDER_VARIANTS:
variant = 'default' Type guard
def is_valid_variant(v: str) -> bool: return v in _VALID_PLACEHOLDER_VARIANTS
Prevention
- Use documented variant names only
- Default instead of passing unchecked config strings
When it happens
Trigger: Placeholder(variant='primary') or placeholder.variant = 'normal' — any misspelled or unsupported variant name.
Common situations: Typos, or assuming variant names from other libraries/CSS class names apply; upgrading Textual where the valid variant set changed.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- {self.name} must be a str (e.g. '10%') or a float (e.g. 0.1)
- Expected a character or hatch value here; found {character!r
- {token!r} is not a valid scalar
- {name!r} is an invalid {description}; identifiers must conta
- invalid value for display (received {new_val!r}, expected {f
AI-assisted analysis of Textualize/textual@06dbeef4bb (2026-08-27).
Data as JSON: /api/errors/1fb84a050f615cca.
Report an issue: GitHub.