{"record":{"id":"09e6bc4844446614","repo":"matplotlib/matplotlib","slug":"cannot-draw-a-line-through-two-identical-points-x","errorCode":null,"errorMessage":"Cannot draw a line through two identical points (x={(x1, x2)}, y={(y1, y2)})","messagePattern":"Cannot draw a line through two identical points \\(x=(.+?), y=(.+?)\\)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"lib/matplotlib/lines.py","lineNumber":1559,"sourceCode":"                \"Exactly one of 'xy2' and 'slope' must be given\")\n\n        self._slope = slope\n        self._xy1 = xy1\n        self._xy2 = xy2\n\n    def get_transform(self):\n        ax = self.axes\n        points_transform = self._transform - ax.transData + ax.transScale\n\n        if self._xy2 is not None:\n            # two points were given\n            (x1, y1), (x2, y2) = \\\n                points_transform.transform([self._xy1, self._xy2])\n            dx = x2 - x1\n            dy = y2 - y1\n            if dx == 0:\n                if dy == 0:\n                    raise ValueError(\n                        f\"Cannot draw a line through two identical points \"\n                        f\"(x={(x1, x2)}, y={(y1, y2)})\")\n                slope = np.inf\n            else:\n                slope = dy / dx\n        else:\n            # one point and a slope were given\n            x1, y1 = points_transform.transform(self._xy1)\n            slope = self._slope\n        (vxlo, vylo), (vxhi, vyhi) = ax.transScale.transform(ax.viewLim)\n        # General case: find intersections with view limits in either\n        # direction, and draw between the middle two points.\n        if slope == 0:\n            start = vxlo, y1\n            stop = vxhi, y1\n        elif np.isinf(slope):\n            start = x1, vylo\n            stop = x1, vyhi","sourceCodeStart":1541,"sourceCodeEnd":1577,"githubUrl":"https://github.com/matplotlib/matplotlib/blob/b379c1b69e012b142c0f496a52bcb30513802d72/lib/matplotlib/lines.py#L1541-L1577","documentation":"When an AxLine defined by two points is drawn, get_transform maps both points to display space to compute the direction. If the transformed points coincide (dx == 0 and dy == 0) the direction is undefined, so a ValueError is raised at draw time, not at the axline() call. Distinct data-space points can still collapse under a nonlinear axis transform: on log scales all non-positive coordinates map to the same clamped value.","triggerScenarios":"ax.axline((1, 1), xy2=(1, 1)) with literally identical points; ax.set_xscale('log') followed by ax.axline((0, 0), xy2=(0, 1)) where both x values collapse under the log transform; data-driven xy2 (min/max pairs) that degenerate to a single point on constant series.","commonSituations":"Fit-through-origin or reference lines on log axes that contain zero or negative data; the error surfacing later at fig.canvas.draw(), plt.show(), or savefig instead of at the axline call; interactive data where xy2 occasionally equals xy1.","solutions":["Make the two points differ before plotting: if xy1 == xy2, perturb xy2 or switch to the slope form","On log axes choose strictly positive, well-separated anchor points","For vertical/horizontal references on log axes prefer ax.axvline/axhline, which are transform-safe","Wrap the first draw in try/except so a degenerate line can be skipped or replaced instead of killing the whole figure"],"exampleFix":"# before\nax.set_xscale('log')\nax.axline((0, 0), xy2=(0, 1))  # both x collapse on log scale -> ValueError at draw\n# after\nax.axline((1, 1), xy2=(2, 2))  # positive, distinct points","handlingStrategy":"try-catch","validationCode":"if tuple(xy1) == tuple(xy2):\n    raise ValueError('axline anchor points must differ')\nif ax.get_xscale() == 'log' or ax.get_yscale() == 'log':\n    assert all(v > 0 for p in (xy1, xy2) for v in p), 'log-scale axline points must be positive'\nline = ax.axline(xy1, xy2=xy2)","typeGuard":null,"tryCatchPattern":"try:\n    line = ax.axline(xy1, xy2=xy2)\n    fig.canvas.draw()  # force get_transform now, not at savefig time\nexcept ValueError as err:\n    if 'identical points' in str(err):\n        line = None  # skip or replace the degenerate line\n    else:\n        raise","preventionTips":["Guard xy1 != xy2 whenever xy2 is computed from data: min/max pairs degenerate on constant series","On log axes keep axline anchor points strictly positive and well separated","Call fig.canvas.draw() right after adding transform-sensitive artists so failures surface at the call site"],"tags":["matplotlib","axline","log-scale","degenerate-input","draw-time"],"backgroundTag":"degenerate-geometry","analyzedSha":"b379c1b69e012b142c0f496a52bcb30513802d72","analyzedAt":"2026-08-21T23:31:55.468Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}