matplotlib/matplotlib · error · ValueError

{name!r} is not 1-dimensional

Error message

{name!r} is not 1-dimensional

What it means

FillBetweenPolyCollection._validate_shapes requires t, f1 and f2 to be 1-dimensional; any input with ndim > 1 raises ValueError naming the offending argument ('x', 'y1'/'x1', 'y2'/'x2' depending on direction). fill_between is a curve API — gridded data belongs to pcolormesh/imshow.

Source

Thrown at lib/matplotlib/collections.py:1561

        """
        if where is None:
            where = True
        else:
            where = np.asarray(where, dtype=bool)
            if where.size != t.size:
                msg = "where size ({}) does not match {!r} size ({})".format(
                    where.size, self.t_direction, t.size)
                raise ValueError(msg)
        return where & ~functools.reduce(
            np.logical_or, map(np.ma.getmaskarray, [t, f1, f2]))

    @staticmethod
    def _validate_shapes(t_dir, f_dir, t, f1, f2):
        """Validate that t, f1 and f2 are 1-dimensional and have the same length."""
        names = (d + s for d, s in zip((t_dir, f_dir, f_dir), ("", "1", "2")))
        for name, array in zip(names, [t, f1, f2]):
            if array.ndim > 1:
                raise ValueError(f"{name!r} is not 1-dimensional")
            if t.size > 1 and array.size > 1 and t.size != array.size:
                msg = "{!r} has size {}, but {!r} has an unequal size of {}".format(
                    t_dir, t.size, name, array.size)
                raise ValueError(msg)

    def _make_verts_for_region(self, t, f1, f2, idx0, idx1):
        """
        Make ``verts`` for a contiguous region between ``idx0`` and ``idx1``, taking
        into account ``step`` and ``interpolate``.
        """
        t_slice = t[idx0:idx1]
        f1_slice = f1[idx0:idx1]
        f2_slice = f2[idx0:idx1]
        if self._step is not None:
            step_func = cbook.STEP_LOOKUP_MAP["steps-" + self._step]
            t_slice, f1_slice, f2_slice = step_func(t_slice, f1_slice, f2_slice)

        if self._interpolate:

View on GitHub (pinned to b379c1b69e)

Solutions

  1. Ravel all inputs: ax.fill_between(x.ravel(), y1.ravel(), y2.ravel())
  2. Select pandas columns as 1D: df['a'].to_numpy(), not df[['a']].to_numpy()
  3. For genuinely 2D fields use pcolormesh/contourf instead of fill_between

Example fix

# before
ax.fill_between(x[:, None], y1, y2)  # x shaped (N, 1) -> 2D

# after
ax.fill_between(x.ravel(), y1.ravel(), y2.ravel())
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np

def as_1d(name, a):
    a = np.asarray(a)
    if a.ndim != 1:
        raise ValueError(f'{name} must be 1D, got ndim={a.ndim}')
    return a

ax.fill_between(as_1d('x', x), as_1d('y1', y1), as_1d('y2', y2))

Type guard

import numpy as np

def is_1d(a) -> bool:
    return np.ndim(a) == 1

Prevention

When it happens

Trigger: ax.fill_between(X, Y1, Y2) with 2D meshgrid-style arrays; passing (N,1) column vectors (e.g. df[['col']].to_numpy()); slicing matrix columns without raveling.

Common situations: Reusing gridded model output in fill_between; pandas column selection with double brackets producing 2D arrays; broadcasting habits carried over from NumPy where they do not apply.

Related errors


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