{"record":{"id":"8371dad1aa9f8b15","repo":"matplotlib/matplotlib","slug":"step-must-be-positive","errorCode":null,"errorMessage":"'step' must be positive","messagePattern":"'step' must be positive","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"lib/matplotlib/ticker.py","lineNumber":2089,"sourceCode":"    \"\"\"\n    Helper for `.MaxNLocator`, `.MultipleLocator`, etc.\n\n    Take floating-point precision limitations into account when calculating\n    tick locations as integer multiples of a step.\n    \"\"\"\n\n    def __init__(self, step, offset):\n        \"\"\"\n        Parameters\n        ----------\n        step : float > 0\n            Interval between ticks.\n        offset : float\n            Offset subtracted from the data limits prior to calculating tick\n            locations.\n        \"\"\"\n        if step <= 0:\n            raise ValueError(\"'step' must be positive\")\n        self.step = step\n        self._offset = abs(offset)\n\n    def closeto(self, ms, edge):\n        # Allow more slop when the offset is large compared to the step.\n        if self._offset > 0:\n            digits = np.log10(self._offset / self.step)\n            tol = max(1e-10, 10 ** (digits - 12))\n            tol = min(0.4999, tol)\n        else:\n            tol = 1e-10\n        return abs(ms - edge) < tol\n\n    def le(self, x):\n        \"\"\"Return the largest n: n*step <= x.\"\"\"\n        d, m = divmod(x, self.step)\n        if self.closeto(m / self.step, 1):\n            return d + 1","sourceCodeStart":2071,"sourceCodeEnd":2107,"githubUrl":"https://github.com/matplotlib/matplotlib/blob/b379c1b69e012b142c0f496a52bcb30513802d72/lib/matplotlib/ticker.py#L2071-L2107","documentation":"_Edge_integer is the internal helper behind MultipleLocator, MaxNLocator and the matplotlib.dates locators that snaps tick positions to integer multiples of a step. Its constructor requires step > 0 because every operation on it divides by the step (divmod-based largest/smallest multiple); zero or negative steps would divide by zero or reverse the tick ladder, so they are rejected immediately.","triggerScenarios":"ticker.MultipleLocator(0) or MultipleLocator(base=-5); a date locator built with a non-positive base/interval, e.g. matplotlib.dates.DayLocator(interval=0) (dates.py constructs _Edge_integer(base, 0) with it); rarely, a MaxNLocator whose internal staircase step degenerates to 0 with pathological data ranges.","commonSituations":"Spacing derived from data, e.g. step = (x.max() - x.min()) / n, which becomes 0 for constant or empty data; passing a negative value intending 'step backwards'; treating interval=0 on date locators as 'use default'.","solutions":["Ensure the value passed to MultipleLocator, or the base/interval of a date locator, is a strictly positive number.","Guard computed spacings: if step <= 0 or not finite, skip installing the locator or clamp to a tiny positive value.","For date locators use interval=1 (or leave it out) rather than 0."],"exampleFix":"import numpy as np\nfrom matplotlib import ticker\n\n// before\nstep = (x.max() - x.min()) / 5  # 0 when x is constant\nax.xaxis.set_major_locator(ticker.MultipleLocator(step))\n\n// after\nstep = (x.max() - x.min()) / 5\nif step > 0:\n    ax.xaxis.set_major_locator(ticker.MultipleLocator(step))\n# else: keep the default AutoLocator","handlingStrategy":"validation","validationCode":"import numpy as np\nfrom matplotlib import ticker\n\ndef safe_tick_step(data, n=5):\n    span = np.ptp(data) if len(data) else 0.0\n    return span / n if span > 0 else None\n\nstep = safe_tick_step(x)\nif step:\n    ax.xaxis.set_major_locator(ticker.MultipleLocator(step))","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Compute tick spacing only after validating the data range is positive.","Treat non-positive or NaN spacings as 'use the default locator' instead of passing them on.","Validate config-supplied base/interval values for MultipleLocator and date locators."],"tags":["matplotlib","multiplelocator","date-locator","tick-spacing","valueerror"],"backgroundTag":"invalid-argument-value","analyzedSha":"b379c1b69e012b142c0f496a52bcb30513802d72","analyzedAt":"2026-08-21T23:31:55.468Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}