{"record":{"id":"1fb84a050f615cca","repo":"Textualize/textual","slug":"valid-placeholder-variants-are-friendly-list-val","errorCode":null,"errorMessage":"Valid placeholder variants are {friendly_list(_VALID_PLACEHOLDER_VARIANTS)}","messagePattern":"Valid placeholder variants are (.+?)","errorType":"exception","errorClass":"InvalidPlaceholderVariant","httpStatus":null,"severity":"error","filePath":"src/textual/widgets/_placeholder.py","lineNumber":172,"sourceCode":"    def cycle_variant(self) -> Self:\n        \"\"\"Get the next variant in the cycle.\n\n        Returns:\n            The `Placeholder` instance.\n        \"\"\"\n        self.variant = next(self._variants_cycle)\n        return self\n\n    def watch_variant(\n        self, old_variant: PlaceholderVariant, variant: PlaceholderVariant\n    ) -> None:\n        self.remove_class(f\"-{old_variant}\")\n        self.add_class(f\"-{variant}\")\n\n    def validate_variant(self, variant: PlaceholderVariant) -> PlaceholderVariant:\n        \"\"\"Validate the variant to which the placeholder was set.\"\"\"\n        if variant not in _VALID_PLACEHOLDER_VARIANTS:\n            raise InvalidPlaceholderVariant(\n                \"Valid placeholder variants are \"\n                + f\"{friendly_list(_VALID_PLACEHOLDER_VARIANTS)}\"\n            )\n        return variant\n\n    async def _on_click(self, _: events.Click) -> None:\n        \"\"\"Click handler to cycle through the placeholder variants.\"\"\"\n        self.cycle_variant()\n\n    def _on_resize(self, event: events.Resize) -> None:\n        \"\"\"Update the placeholder \"size\" variant with the new placeholder size.\"\"\"\n        self._renderables[\"size\"] = self._SIZE_RENDER_TEMPLATE.format(*event.size)\n        if self.variant == \"size\":\n            self.refresh()\n","sourceCodeStart":154,"sourceCodeEnd":187,"githubUrl":"https://github.com/Textualize/textual/blob/06dbeef4bb70fb718236aa418ed658ef4667a126/src/textual/widgets/_placeholder.py#L154-L187","documentation":"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.","triggerScenarios":"Placeholder(variant='primary') or placeholder.variant = 'normal' — any misspelled or unsupported variant name.","commonSituations":"Typos, or assuming variant names from other libraries/CSS class names apply; upgrading Textual where the valid variant set changed.","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'."],"exampleFix":"# before\nPlaceholder(variant='textwidget')\n# after\nPlaceholder(variant='text-widgets')","handlingStrategy":"type-guard","validationCode":"from textual.widgets._placeholder import _VALID_PLACEHOLDER_VARIANTS\nif variant not in _VALID_PLACEHOLDER_VARIANTS:\n    variant = 'default'","typeGuard":"def is_valid_variant(v: str) -> bool: return v in _VALID_PLACEHOLDER_VARIANTS","tryCatchPattern":null,"preventionTips":["Use documented variant names only","Default instead of passing unchecked config strings"],"tags":["placeholder","validation","textual","variant"],"backgroundTag":"invalid-enum-value","analyzedSha":"06dbeef4bb70fb718236aa418ed658ef4667a126","analyzedAt":"2026-08-27T02:36:57.214Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}