matplotlib/matplotlib · error · TypeError
autopct must be callable or a format string
Error message
autopct must be callable or a format string
What it means
Axes.pie raises this TypeError when the autopct argument is neither a string nor a callable. autopct annotates each wedge with its percentage and supports exactly two forms: a printf-style format string (which receives 100*frac) or a function taking the percentage. None is allowed and disables percentage labels.
Source
Thrown at lib/matplotlib/axes/_axes.py:3822
# Add labels to the wedges.
labels_textprops = {
'fontsize': mpl.rcParams['xtick.labelsize'],
**cbook.normalize_kwargs(textprops or {}, Text)
}
self.pie_label(pc, labels, distance=labeldistance,
alignment='outer', rotate=rotatelabels,
textprops=labels_textprops)
if autopct is not None:
# Add automatic percentage labels to wedges
auto_labels = []
for frac in fracs:
if isinstance(autopct, str):
s = autopct % (100. * frac)
elif callable(autopct):
s = autopct(100. * frac)
else:
raise TypeError(
'autopct must be callable or a format string')
if textprops is not None and mpl._val_or_rc(textprops.get("usetex"),
"text.usetex"):
# escape % (i.e. \%) if it is not already escaped
s = re.sub(r"([^\\])%", r"\1\\%", s)
auto_labels.append(s)
self.pie_label(pc, auto_labels, distance=pctdistance,
alignment='center',
textprops=textprops)
if frame:
self._request_autoscale_view()
else:
self.set(frame_on=False, xticks=[], yticks=[],
xlim=(-1.25 + center[0], 1.25 + center[0]),
ylim=(-1.25 + center[1], 1.25 + center[1]))
View on GitHub (pinned to b379c1b69e)
Solutions
- Use a format string: autopct='%1.1f%%' (the literal percent must be escaped as %%).
- Or a callable: autopct=lambda pct: f'{pct:.1f}%'.
- If you meant one custom label per wedge, use labels or wedge_labels instead of autopct.
- Pass autopct=None to disable percentage labels entirely.
Example fix
# before
ax.pie(x, autopct=['10%', '20%', '70%']) # list of strings is not accepted
# after
ax.pie(x, autopct='%1.1f%%') # or autopct=lambda pct: f'{pct:.1f}%' Defensive patterns
Strategy: type-guard
Validate before calling
assert autopct is None or isinstance(autopct, str) or callable(autopct), \
'autopct must be a format string or a callable'
ax.pie(x, autopct=autopct) Type guard
def is_valid_autopct(autopct) -> bool:
return autopct is None or isinstance(autopct, str) or callable(autopct) Prevention
- Remember the two accepted forms: '%1.1f%%' or a lambda over the percentage.
- Per-wedge custom text belongs in labels/wedge_labels, not autopct.
- Escape literal percent signs as %% inside the format string.
When it happens
Trigger: ax.pie(x, autopct=5) or ax.pie(x, autopct=['10%', '20%', '70%']) - a number or a list of strings is rejected. Also passing a preformatted percent value instead of a template.
Common situations: Assuming autopct takes a number (e.g. autopct=1 meaning '1 decimal'); passing one custom string per wedge (that belongs in labels/wedge_labels); copy-pasting examples where autopct was a lambda and replacing it with a value.
Understand the failure class
Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.
Related errors
- 'labels' must be of length 'x', not {len(labels)}
- 'explode' must be of length 'x', not {len(explode)}
- 'radius' must be a positive number, not {radius}
- The number of labels ({nl}) must match the number of wedges
- {errorevery=!r} is a not a tuple of two integers
AI-assisted analysis of matplotlib/matplotlib@b379c1b69e (2026-08-21).
Data as JSON: /api/errors/cd024771abb0e6f6.
Report an issue: GitHub.