matplotlib/matplotlib · error · ValueError

`rotation_point` must be one of {'xy', 'center', (number, nu

Error message

`rotation_point` must be one of {'xy', 'center', (number, number)}.

What it means

Rectangle accepts a rotation_point ('xy' by default) that fixes the pivot used when rotating the rectangle via its angle attribute: allowed values are the strings 'center' and 'xy' or a tuple of two Real numbers. The setter validates this union and raises ValueError("`rotation_point` must be one of {'xy', 'center', (number, number)}.") for anything else. Note the type strictness: a list [x, y] or a numpy array is rejected because only tuple passes the isinstance check, and 1-element or 3-element tuples fail too.

Source

Thrown at lib/matplotlib/patches.py:916

                .scale(1, self._aspect_ratio_correction) \
                .rotate_deg(self.angle) \
                .scale(1, 1 / self._aspect_ratio_correction) \
                .translate(*rotation_point)

    @property
    def rotation_point(self):
        """The rotation point of the patch."""
        return self._rotation_point

    @rotation_point.setter
    def rotation_point(self, value):
        if value in ['center', 'xy'] or (
                isinstance(value, tuple) and len(value) == 2 and
                isinstance(value[0], Real) and isinstance(value[1], Real)
                ):
            self._rotation_point = value
        else:
            raise ValueError("`rotation_point` must be one of "
                             "{'xy', 'center', (number, number)}.")

    def get_x(self):
        """Return the left coordinate of the rectangle."""
        return self._x0

    def get_y(self):
        """Return the bottom coordinate of the rectangle."""
        return self._y0

    def get_xy(self):
        """Return the left and bottom coords of the rectangle as a tuple."""
        return self._x0, self._y0

    def get_corners(self):
        """
        Return the corners of the rectangle, moving anti-clockwise from
        (x0, y0).

View on GitHub (pinned to b379c1b69e)

Solutions

  1. Use 'center' or 'xy' for named pivots.
  2. For a custom pivot pass a 2-tuple of numbers: rect.rotation_point = (0.5, 0.5).
  3. Coerce dynamic inputs: tuple(map(float, value)) before assignment.
  4. Compute the wanted pivot from the rectangle bbox: (rect.get_x() + w/2, rect.get_y() + h/2) reproduces 'center' if you need numeric control.

Example fix

# before
rect = Rectangle((0, 0), 2, 1, angle=30, rotation_point=[0.5, 0.5])

# after
rect = Rectangle((0, 0), 2, 1, angle=30, rotation_point=(1.0, 0.5))
# or a named pivot: rotation_point='center'
Defensive patterns

Strategy: type-guard

Validate before calling

from numbers import Real

def coerce_rotation_point(v):
    if isinstance(v, (list, np.ndarray)):
        v = tuple(v)
    if not (v in ('xy', 'center') or (
            isinstance(v, tuple) and len(v) == 2
            and all(isinstance(c, Real) for c in v))):
        raise ValueError(f'bad rotation_point: {v!r}')
    return v

Type guard

def is_valid_rotation_point(v) -> bool:
    from numbers import Real
    return v in ('xy', 'center') or (
        isinstance(v, tuple) and len(v) == 2
        and isinstance(v[0], Real) and isinstance(v[1], Real))

Prevention

When it happens

Trigger: rect.rotation_point = 'left' or 'top' (not supported); rect.rotation_point = [0.5, 0.5] (list, not tuple); rect.rotation_point = (0.5,) (wrong length); Rectangle(..., rotation_point='center bottom') copied from other APIs.

Common situations: Users expecting anchor strings like those of AnchoredOffsetbox ('upper left'); passing JSON-decoded coordinates (always lists); interpolating a pivot from config as a list instead of a tuple; interactive rectangle-rotation tools (e.g. widgets.RectangleSelector ecosystem) setting arbitrary pivots.

Understand the failure class

Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.

Related errors


AI-assisted analysis of matplotlib/matplotlib@b379c1b69e (2026-08-21). Data as JSON: /api/errors/9fa00d7cea1a4dc6. Report an issue: GitHub.