matplotlib/matplotlib · error · TypeError

subplot() got an unexpected keyword argument 'ncols' and/or

Error message

subplot() got an unexpected keyword argument 'ncols' and/or 'nrows'.  Did you intend to call subplots()?

What it means

plt.subplot() (singular) places ONE axes in a figure using positional integers (nrows, ncols, index); it does not accept nrows/ncols as keywords. Passing either raises TypeError('subplot() got an unexpected keyword argument ... Did you intend to call subplots()?') - a deliberate typo-trap for the very common slip of calling subplot() when a whole grid via plt.subplots(nrows=..., ncols=...) was meant. The related bool-as-index case only warns, but nrows/ncols hard-errors.

Source

Thrown at lib/matplotlib/pyplot.py:1653

            )
        kwargs['projection'] = projection = 'polar'

    # if subplot called without arguments, create subplot(1, 1, 1)
    if len(args) == 0:
        args = (1, 1, 1)

    # This check was added because it is very easy to type subplot(1, 2, False)
    # when subplots(1, 2, False) was intended (sharex=False, that is). In most
    # cases, no error will ever occur, but mysterious behavior can result
    # because what was intended to be the sharex argument is instead treated as
    # a subplot index for subplot()
    if len(args) >= 3 and isinstance(args[2], bool):
        _api.warn_external("The subplot index argument to subplot() appears "
                           "to be a boolean. Did you intend to use "
                           "subplots()?")
    # Check for nrows and ncols, which are not valid subplot args:
    if 'nrows' in kwargs or 'ncols' in kwargs:
        raise TypeError("subplot() got an unexpected keyword argument 'ncols' "
                        "and/or 'nrows'.  Did you intend to call subplots()?")

    fig = gcf()

    # First, search for an existing subplot with a matching spec.
    key = SubplotSpec._from_subplot_args(fig, args)

    for ax in fig.axes:
        # If we found an Axes at the position, we can reuse it if the user passed no
        # kwargs or if the Axes class and kwargs are identical.
        if (ax.get_subplotspec() == key
            and (kwargs == {}
                 or (ax._projection_init
                     == fig._process_projection_requirements(**kwargs)))):
            break
    else:
        # we have exhausted the known Axes and none match, make a new one!
        ax = fig.add_subplot(*args, **kwargs)

View on GitHub (pinned to b379c1b69e)

Solutions

  1. If you want the whole grid at once, call plt.subplots(2, 2) (returns fig, ax array)
  2. If you want one panel, pass the spec positionally: plt.subplot(2, 2, 1)
  3. Search the codebase for 'subplot(nrows' / 'subplot(ncols' - every hit is this bug

Example fix

# before
fig, ax = plt.subplot(nrows=2, ncols=2)  # TypeError: did you mean subplots()?

# after
fig, axs = plt.subplots(nrows=2, ncols=2)
Defensive patterns

Strategy: validation

Validate before calling

def subplot_or_subplots(**kw):
    if {'nrows', 'ncols'} & set(kw):
        raise TypeError('nrows/ncols belong to plt.subplots(); use it instead')
    return plt.subplot(**kw)

Prevention

When it happens

Trigger: plt.subplot(nrows=2, ncols=2); plt.subplot(2, 2, 1, ncols=2); refactoring plt.subplots(2, 2) into per-panel calls and keeping the keyword style; autocomplete choosing subplot over subplots.

Common situations: The singular/plural API pair is matplotlib's most common name confusion; IDE autocompletion picking the shorter name; code converted from object API (fig.subplots) back to pyplot.

Related errors


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