matplotlib/matplotlib · error · ValueError
{coords!r} is not a valid coordinate
Error message
{coords!r} is not a valid coordinate What it means
In Annotation._get_xy_transform: string xycoords values other than the bare keywords 'data' and 'polar' must be exactly two whitespace-separated words - a reference-box name plus a unit, like 'axes fraction'. coords.split() must yield two parts; if it yields one (or three), this ValueError is raised.
Source
Thrown at lib/matplotlib/text.py:1783
elif isinstance(coords, BboxBase):
return BboxTransformTo(coords)
elif isinstance(coords, Transform):
return coords
elif not isinstance(coords, str):
raise TypeError(
f"'xycoords' must be an instance of str, tuple[str, str], Artist, "
f"Transform, or Callable, not a {type(coords).__name__}")
if coords == 'data':
return self.axes.transData
elif coords == 'polar':
from matplotlib.projections import PolarAxes
return PolarAxes.PolarTransform() + self.axes.transData
try:
bbox_name, unit = coords.split()
except ValueError: # i.e. len(coords.split()) != 2.
raise ValueError(f"{coords!r} is not a valid coordinate") from None
bbox0, xy0 = None, None
# if unit is offset-like
if bbox_name == "figure":
bbox0 = self.get_figure(root=False).figbbox
elif bbox_name == "subfigure":
bbox0 = self.get_figure(root=False).bbox
elif bbox_name == "axes":
bbox0 = self.axes.bbox
# reference x, y in display coordinate
if bbox0 is not None:
xy0 = bbox0.p0
elif bbox_name == "offset":
xy0 = self._get_position_xy(renderer)
else:
raise ValueError(f"{coords!r} is not a valid coordinate")View on GitHub (pinned to b379c1b69e)
Solutions
- Use complete two-word specs: 'figure points', 'figure pixels', 'figure fraction', 'subfigure ...', 'axes points', 'axes pixels', 'axes fraction', or 'offset <unit>'.
- Check typos and concatenations - the string must contain whitespace between the name and the unit.
- For per-axis tuples, make each element a valid spec by itself: ('axes fraction', 'data').
Example fix
# before
ax.annotate('a', xy=(0.5, 0.5), xycoords='axes') # ValueError
# after
ax.annotate('a', xy=(0.5, 0.5), xycoords='axes fraction') Defensive patterns
Strategy: validation
Validate before calling
BOXES = {'figure', 'subfigure', 'axes', 'offset'}
UNITS = {'points', 'pixels', 'fraction', 'fontsize'}
def valid_coord_string(c):
if c in ('data', 'polar'):
return True
parts = c.split()
return len(parts) == 2 and parts[0] in BOXES and parts[1] in UNITS Prevention
- String specs are two words: '<box> <unit>' (e.g. 'axes fraction'), except the bare 'data' and 'polar'.
- Validate config-supplied spec strings against the box/unit vocabulary before annotating.
- In per-axis tuples, each element must itself be a valid spec.
When it happens
Trigger: xycoords='axes' (missing unit); xycoords='figure fraction extra'; typos like 'axes fraction' are fine (split() handles runs) but 'axesfraction' is one word and fails; a bare unknown keyword like 'screen' also fails here since only 'data' and 'polar' are special-cased.
Common situations: Config-driven annotation systems where users type half the spec; porting code that used a single-word spec from another library; forgetting that per-axis tuples must have two-word strings in each slot, e.g. ('axes', 'data') fails on 'axes'.
Related errors
- {unit!r} is not a recognized unit
- xycoords cannot be an offset coordinate
- {s0} is not a valid coordinate transformation
- xycoords callable must return a BboxBase or Transform, not a
- 'xycoords' must be an instance of str, tuple[str, str], Arti
AI-assisted analysis of matplotlib/matplotlib@b379c1b69e (2026-08-21).
Data as JSON: /api/errors/9facbdfd83a03c87.
Report an issue: GitHub.