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
- If you want the whole grid at once, call plt.subplots(2, 2) (returns fig, ax array)
- If you want one panel, pass the spec positionally: plt.subplot(2, 2, 1)
- 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
- plt.subplot (one panel, positional ints) vs plt.subplots (whole grid, keywords) - memorize the pair
- Never pass nrows/ncols as keywords to subplot(); the spec is positional (nrows, ncols, index)
- Code-review grep for 'subplot(nrows' and 'subplot(ncols' catches every instance of this slip
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
- num {num!r} cannot be a FigureBase instance. plt.{func_name}
- Figure {num!r} already exists. Use plt.figure({num!r}) to ge
- polar={polar}, yet projection={projection!r}. Only one of th
- xticks(): Parameter 'labels' can't be set without setting 't
- yticks(): Parameter 'labels' can't be set without setting 't
AI-assisted analysis of matplotlib/matplotlib@b379c1b69e (2026-08-21).
Data as JSON: /api/errors/2345949904279235.
Report an issue: GitHub.