matplotlib/matplotlib · error · ValueError

aspect must be finite and positive

Error message

aspect must be finite and positive 

What it means

set_aspect() accepts the strings 'auto' and 'equal', or a number; numbers are coerced with float() and must be strictly positive and finite. Zero, negatives, NaN, and inf are rejected (lib/matplotlib/axes/_base.py:1710). Non-numeric strings fail earlier inside float().

Source

Thrown at lib/matplotlib/axes/_base.py:1710

        one depends on *adjustable*). This update is applied lazily, the latest
        when the figure is drawn. Use `.apply_aspect` to force an update.

        See Also
        --------
        matplotlib.axes.Axes.set_adjustable
            Set how the Axes adjusts to achieve the required aspect ratio.
        matplotlib.axes.Axes.set_anchor
            Set the position in case of extra space.
        matplotlib.axes.Axes.apply_aspect
            Force the update required to meet the aspect ratio to happen
            immediately.
        """
        if cbook._str_equal(aspect, 'equal'):
            aspect = 1
        if not cbook._str_equal(aspect, 'auto'):
            aspect = float(aspect)  # raise ValueError if necessary
            if aspect <= 0 or not np.isfinite(aspect):
                raise ValueError("aspect must be finite and positive ")

        if share:
            axes = {sibling for name in self._axis_names
                    for sibling in self._shared_axes[name].get_siblings(self)}
        else:
            axes = [self]

        for ax in axes:
            ax._aspect = aspect

        if adjustable is None:
            adjustable = self._adjustable
        self.set_adjustable(adjustable, share=share)  # Handle sharing.

        if anchor is not None:
            self.set_anchor(anchor, share=share)
        self.stale = True

View on GitHub (pinned to b379c1b69e)

Solutions

  1. Guard computed ratios: aspect = dy / dx if dx else 1
  2. Use the strings 'equal' or 'auto' when you mean those modes
  3. Validate numeric config before calling: math.isfinite(aspect) and aspect > 0

Example fix

# before
ax.set_aspect(yrange / xrange)  # xrange == 0 -> inf
# after
ax.set_aspect(yrange / xrange if xrange else 1)
Defensive patterns

Strategy: validation

Validate before calling

import math

def valid_aspect(a) -> bool:
    return isinstance(a, str) or (isinstance(a, (int, float)) and math.isfinite(a) and a > 0)

assert valid_aspect(aspect), f'invalid aspect {aspect!r}'

Type guard

import math

def is_valid_aspect(a) -> bool:
    return a in ('auto', 'equal') or (isinstance(a, (int, float)) and math.isfinite(a) and a > 0)

Prevention

When it happens

Trigger: ax.set_aspect(0), ax.set_aspect(-2), ax.set_aspect(np.nan), ax.set_aspect(np.inf); or an aspect computed as dy/dx where one data range collapsed to 0 (yielding inf or nan).

Common situations: Aspect derived from data extents where a range collapsed (division by zero); unvalidated user config values; passing invented strings like 'equalXY' that float() cannot parse.

Related errors


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