matplotlib/matplotlib · error · RuntimeError

xdata must be a sequence

Error message

xdata must be a sequence

What it means

Line2D.__init__ requires xdata to be iterable; np.iterable(xdata) returned False, so a scalar number, None, or other non-iterable object was passed as the x data. matplotlib stores line data as arrays and cannot construct a line artist from a single bare value.

Source

Thrown at lib/matplotlib/lines.py:362

                 ):
        """
        Create a `.Line2D` instance with *x* and *y* data in sequences of
        *xdata*, *ydata*.

        Additional keyword arguments are `.Line2D` properties:

        %(Line2D:kwdoc)s

        See :meth:`set_linestyle` for a description of the line styles,
        :meth:`set_marker` for a description of the markers, and
        :meth:`set_drawstyle` for a description of the draw styles.

        """
        super().__init__()

        # Convert sequences to NumPy arrays.
        if not np.iterable(xdata):
            raise RuntimeError('xdata must be a sequence')
        if not np.iterable(ydata):
            raise RuntimeError('ydata must be a sequence')

        linewidth = mpl._val_or_rc(linewidth, 'lines.linewidth')
        linestyle = mpl._val_or_rc(linestyle, 'lines.linestyle')
        marker = mpl._val_or_rc(marker, 'lines.marker')
        color = mpl._val_or_rc(color, 'lines.color')
        markersize = mpl._val_or_rc(markersize, 'lines.markersize')
        antialiased = mpl._val_or_rc(antialiased, 'lines.antialiased')
        dash_capstyle = mpl._val_or_rc(dash_capstyle, 'lines.dash_capstyle')
        dash_joinstyle = mpl._val_or_rc(dash_joinstyle, 'lines.dash_joinstyle')
        solid_capstyle = mpl._val_or_rc(solid_capstyle, 'lines.solid_capstyle')
        solid_joinstyle = mpl._val_or_rc(solid_joinstyle, 'lines.solid_joinstyle')

        if drawstyle is None:
            drawstyle = 'default'

        self._dashcapstyle = None

View on GitHub (pinned to b379c1b69e)

Solutions

  1. Wrap the scalar in a list: Line2D([3], [4])
  2. Use ax.plot(3, 4) or ax.scatter([3], [4]), which coerce scalar arguments for you
  3. Collect values into a list first when plotting in a loop, then construct the line once

Example fix

# before
line = Line2D(3, 4)
# after
line = Line2D([3], [4])
Defensive patterns

Strategy: type-guard

Validate before calling

import numpy as np
if not np.iterable(xdata):
    xdata = [xdata]
line = Line2D(xdata, ydata)

Type guard

import numpy as np

def is_sequence(v) -> bool:
    return np.iterable(v) and not isinstance(v, (str, bytes))

Try / catch

try:
    line = Line2D(x, y)
except RuntimeError as err:
    if 'must be a sequence' in str(err):
        x = [x] if not np.iterable(x) else x
        line = Line2D(x, y)
    else:
        raise

Prevention

When it happens

Trigger: Constructing Line2D directly with scalars: Line2D(3, 4); Line2D(np.float64(1.0), y); Line2D(None, y); passing a bare Python or numpy scalar object that defines no __iter__.

Common situations: Bypassing ax.plot (which wraps scalars into length-1 arrays) by instantiating Line2D directly; plotting inside a loop and passing the loop variable instead of the collected list; passing an unpacked scalar where a sequence was expected.

Related errors


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