Textualize/rich · error · ValueError
invalid value for vertical, expected "top", "middle", or "bo
Error message
invalid value for vertical, expected "top", "middle", or "bottom" (not {vertical!r}) What it means
Align.__init__ validates the keyword-only vertical argument: it must be None or one of "top", "middle", "bottom", otherwise ValueError. Unlike align, vertical is optional and defaults to None (no vertical alignment). The literal "middle" is used here, not "center" — a common source of confusion since horizontal alignment uses "center".
Source
Thrown at rich/align.py:63
"""
def __init__(
self,
renderable: "RenderableType",
align: AlignMethod = "left",
style: Optional[StyleType] = None,
*,
vertical: Optional[VerticalAlignMethod] = None,
pad: bool = True,
width: Optional[int] = None,
height: Optional[int] = None,
) -> None:
if align not in ("left", "center", "right"):
raise ValueError(
f'invalid value for align, expected "left", "center", or "right" (not {align!r})'
)
if vertical is not None and vertical not in ("top", "middle", "bottom"):
raise ValueError(
f'invalid value for vertical, expected "top", "middle", or "bottom" (not {vertical!r})'
)
self.renderable = renderable
self.align = align
self.style = style
self.vertical = vertical
self.pad = pad
self.width = width
self.height = height
def __repr__(self) -> str:
return f"Align({self.renderable!r}, {self.align!r})"
@classmethod
def left(
cls,
renderable: "RenderableType",
style: Optional[StyleType] = None,View on GitHub (pinned to 9d8f9a372c)
Solutions
- Use exactly "top", "middle", or "bottom" (note: "middle", not "center")
- Omit the vertical argument or pass None if no vertical alignment is wanted
- Normalize user config values (strip().lower()) before passing them in
Example fix
// before (Python) Align(panel, vertical="center") # ValueError // after Align(panel, vertical="middle") # or omit / pass None
Defensive patterns
Strategy: type-guard
Validate before calling
vertical = None if raw in (None, "") else str(raw).strip().lower()
if vertical is not None and vertical not in ("top", "middle", "bottom"):
raise ValueError(f"vertical must be top/middle/bottom, got {raw!r}")
render = Align(panel, vertical=vertical) Type guard
from typing import Literal, TypeGuard
VerticalAlignMethod = Literal["top", "middle", "bottom"]
def is_vertical_align(v: object) -> TypeGuard[VerticalAlignMethod]:
return v in ("top", "middle", "bottom") Prevention
- Remember the asymmetry: horizontal is 'center', vertical is 'middle'
- Use None to disable vertical alignment, never an empty string
- Lint config files for allowed vertical values at startup
When it happens
Trigger: Calling Align(renderable, vertical="center") (mixing up the horizontal term), vertical="top " with stray whitespace, or passing an empty string instead of None. Passing a vertical value via unpacked kwargs from a settings dict is another common route.
Common situations: Developers writing vertical="center" by analogy with align="center"; config-driven layouts where "center" is used for both axes; forgetting that None (not "") disables vertical alignment.
Related errors
- invalid value for align, expected "left", "center", or "righ
- level must be 'head', 'row' or 'foot'
- 'characters' argument must have a cell width of at least 1
- invalid value for align, expected "left", "center", "right"
- {original_color!r} is not a valid color
AI-assisted analysis of Textualize/rich@9d8f9a372c (2026-08-15).
Data as JSON: /api/errors/c638e107e8fc791f.
Report an issue: GitHub.