matplotlib/matplotlib · error · ValueError

Collections can only map rank 1 arrays

Error message

Collections can only map rank 1 arrays

What it means

Collection.update_scalarmappable maps the mappable array (_A) through the colormap at draw time. Regular collections (LineCollection, PolyCollection, PathCollection) accept only rank-1 arrays — one value per element; if _A.ndim > 1 and the class is not a _MeshData subclass (QuadMesh, supplied 1D by pcolormesh), it raises ValueError.

Source

Thrown at lib/matplotlib/collections.py:1025

        changed = (edge0 is None or face0 is None
                   or self._edge_is_mapped != edge0
                   or self._face_is_mapped != face0)
        return mapped or changed

    def update_scalarmappable(self):
        """
        Update colors from the scalar mappable array, if any.

        Assign colors to edges and faces based on the array and/or
        colors that were directly set, as appropriate.
        """
        if not self._set_mappable_flags():
            return
        # Allow possibility to call 'self.set_array(None)'.
        if self._A is not None:
            # QuadMesh can map 2d arrays (but pcolormesh supplies 1d array)
            if self._A.ndim > 1 and not isinstance(self, _MeshData):
                raise ValueError('Collections can only map rank 1 arrays')
            if np.iterable(self._alpha):
                if self._alpha.size != self._A.size:
                    raise ValueError(
                        f'Data array shape, {self._A.shape} '
                        'is incompatible with alpha array shape, '
                        f'{self._alpha.shape}. '
                        'This can occur with the deprecated '
                        'behavior of the "flat" shading option, '
                        'in which a row and/or column of the data '
                        'array is dropped.')
                # pcolormesh, scatter, maybe others flatten their _A
                self._alpha = self._alpha.reshape(self._A.shape)
            self._mapped_colors = self.to_rgba(self._A, self._alpha)

        if self._face_is_mapped:
            self._facecolors = self._mapped_colors
        else:
            self._set_facecolor(self._original_facecolor)

View on GitHub (pinned to b379c1b69e)

Solutions

  1. Flatten the array: coll.set_array(arr.ravel())
  2. Keep genuinely 2D fields on QuadMesh/pcolormesh or imshow, which are built for them
  3. Check the flattened length matches the number of elements: len(coll.get_paths()) or coll.get_offsets()

Example fix

# before
coll.set_array(np.zeros((10, 10)))

# after
coll.set_array(np.zeros((10, 10)).ravel())
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np

def set_array_1d(coll, arr):
    a = np.asarray(arr)
    if a.ndim != 1:
        a = a.ravel()
    coll.set_array(a)

set_array_1d(coll, np.zeros((10, 10)))

Type guard

import numpy as np

def is_rank1(a) -> bool:
    return getattr(a, 'ndim', 1) == 1

Try / catch

try:
    coll.set_array(arr); fig.canvas.draw()
except ValueError as e:
    if 'rank 1' in str(e):
        coll.set_array(np.asarray(arr).ravel())
    else:
        raise

Prevention

When it happens

Trigger: coll = LineCollection(...); coll.set_array(np.zeros((10, 10))); then any draw, colorbar, or autoscale triggers update_scalarmappable. Also passing a (N,1) column array instead of (N,) to a collection's set_array.

Common situations: Porting pcolormesh/imshow-style 2D gridded data onto a generic collection; custom Collection subclasses expected to behave like a mesh; forgetting that scatter flattens c for you while direct set_array does not.

Related errors


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