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

  1. Use a format string: autopct='%1.1f%%' (the literal percent must be escaped as %%).
  2. Or a callable: autopct=lambda pct: f'{pct:.1f}%'.
  3. If you meant one custom label per wedge, use labels or wedge_labels instead of autopct.
  4. 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

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


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