{"record":{"id":"2510d120b91879b3","repo":"matplotlib/matplotlib","slug":"aspect-must-be-finite-and-positive","errorCode":null,"errorMessage":"aspect must be finite and positive ","messagePattern":"aspect must be finite and positive ","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"lib/matplotlib/axes/_base.py","lineNumber":1710,"sourceCode":"        one depends on *adjustable*). This update is applied lazily, the latest\n        when the figure is drawn. Use `.apply_aspect` to force an update.\n\n        See Also\n        --------\n        matplotlib.axes.Axes.set_adjustable\n            Set how the Axes adjusts to achieve the required aspect ratio.\n        matplotlib.axes.Axes.set_anchor\n            Set the position in case of extra space.\n        matplotlib.axes.Axes.apply_aspect\n            Force the update required to meet the aspect ratio to happen\n            immediately.\n        \"\"\"\n        if cbook._str_equal(aspect, 'equal'):\n            aspect = 1\n        if not cbook._str_equal(aspect, 'auto'):\n            aspect = float(aspect)  # raise ValueError if necessary\n            if aspect <= 0 or not np.isfinite(aspect):\n                raise ValueError(\"aspect must be finite and positive \")\n\n        if share:\n            axes = {sibling for name in self._axis_names\n                    for sibling in self._shared_axes[name].get_siblings(self)}\n        else:\n            axes = [self]\n\n        for ax in axes:\n            ax._aspect = aspect\n\n        if adjustable is None:\n            adjustable = self._adjustable\n        self.set_adjustable(adjustable, share=share)  # Handle sharing.\n\n        if anchor is not None:\n            self.set_anchor(anchor, share=share)\n        self.stale = True\n","sourceCodeStart":1692,"sourceCodeEnd":1728,"githubUrl":"https://github.com/matplotlib/matplotlib/blob/b379c1b69e012b142c0f496a52bcb30513802d72/lib/matplotlib/axes/_base.py#L1692-L1728","documentation":"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().","triggerScenarios":"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).","commonSituations":"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.","solutions":["Guard computed ratios: aspect = dy / dx if dx else 1","Use the strings 'equal' or 'auto' when you mean those modes","Validate numeric config before calling: math.isfinite(aspect) and aspect > 0"],"exampleFix":"# before\nax.set_aspect(yrange / xrange)  # xrange == 0 -> inf\n# after\nax.set_aspect(yrange / xrange if xrange else 1)","handlingStrategy":"validation","validationCode":"import math\n\ndef valid_aspect(a) -> bool:\n    return isinstance(a, str) or (isinstance(a, (int, float)) and math.isfinite(a) and a > 0)\n\nassert valid_aspect(aspect), f'invalid aspect {aspect!r}'","typeGuard":"import math\n\ndef is_valid_aspect(a) -> bool:\n    return a in ('auto', 'equal') or (isinstance(a, (int, float)) and math.isfinite(a) and a > 0)","tryCatchPattern":null,"preventionTips":["Never feed raw dy/dx into set_aspect without handling zero ranges","Centralize aspect computation in one guarded helper","Reject non-finite config values early with a clear message"],"tags":["matplotlib","aspect","numeric-validation","nan","inf"],"backgroundTag":"invalid-aspect-ratio","analyzedSha":"b379c1b69e012b142c0f496a52bcb30513802d72","analyzedAt":"2026-08-21T23:31:55.468Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}