matplotlib/matplotlib · error · ValueError

Multiple spines must be passed as a single list

Error message

Multiple spines must be passed as a single list

What it means

Spines.__getitem__ accepts a single name (string), a list of names, or the fully open slice [:]. Indexing with a tuple - classically ax.spines[('top', 'right')] written where ax.spines[['top', 'right']] was meant - raises this ValueError; the message states the fix: multiple names must be passed as a single list.

Source

Thrown at lib/matplotlib/spines.py:601

    def __setstate__(self, state):
        self.__init__(**state)

    def __getattr__(self, name):
        try:
            return self._dict[name]
        except KeyError:
            raise AttributeError(
                f"'Spines' object does not contain a '{name}' spine")

    def __getitem__(self, key):
        if isinstance(key, list):
            unknown_keys = [k for k in key if k not in self._dict]
            if unknown_keys:
                raise KeyError(', '.join(unknown_keys))
            return SpinesProxy({k: v for k, v in self._dict.items()
                                if k in key})
        if isinstance(key, tuple):
            raise ValueError('Multiple spines must be passed as a single list')
        if isinstance(key, slice):
            if key.start is None and key.stop is None and key.step is None:
                return SpinesProxy(self._dict)
            else:
                raise ValueError(
                    'Spines does not support slicing except for the fully '
                    'open slice [:] to access all spines.')
        return self._dict[key]

    def __setitem__(self, key, value):
        # TODO: Do we want to deprecate adding spines?
        self._dict[key] = value

    def __delitem__(self, key):
        # TODO: Do we want to deprecate deleting spines?
        del self._dict[key]

    def __iter__(self):

View on GitHub (pinned to b379c1b69e)

Solutions

  1. Use a list: ax.spines[['top', 'right']].set_visible(False)
  2. Address all spines with ax.spines[:]
  3. Normalize keys before indexing: names = list(names) if isinstance(names, tuple) else names

Example fix

# before
ax.spines[('top', 'right')].set_visible(False)  # ValueError

# after
ax.spines[['top', 'right']].set_visible(False)
Defensive patterns

Strategy: validation

Validate before calling

def spine_keys(names):
    if isinstance(names, tuple):
        names = list(names)  # tuple key would raise inside __getitem__
    return names

ax.spines[spine_keys(('top', 'right'))].set_visible(False)

Prevention

When it happens

Trigger: ax.spines[('top', 'right')].set_visible(False) - parentheses around the names instead of a list literal; programmatic key building that produces a tuple.

Common situations: Habits carried over from pandas .loc tuple indexing or numpy multi-axis indexing; list-vs-tuple normalization missing in helper functions.

Related errors


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