matplotlib/matplotlib · error · TypeError

cycler() must have positional OR keyword arguments

Error message

cycler() must have positional OR keyword arguments

What it means

matplotlib.rcsetup.cycler() (lib/matplotlib/rcsetup.py:790) raises TypeError when called with neither positional nor keyword arguments. A cycler must cycle over at least one artist property, so an empty call is rejected before any validation happens.

Source

Thrown at lib/matplotlib/rcsetup.py:790

    Examples
    --------
    Creating a cycler for a single property:

    >>> c = cycler(color=['red', 'green', 'blue'])

    Creating a cycler for simultaneously cycling over multiple properties
    (e.g. red circle, green plus, blue cross):

    >>> c = cycler(color=['red', 'green', 'blue'],
    ...            marker=['o', '+', 'x'])

    """
    if args and kwargs:
        raise TypeError("cycler() can only accept positional OR keyword "
                        "arguments -- not both.")
    elif not args and not kwargs:
        raise TypeError("cycler() must have positional OR keyword arguments")

    if len(args) == 1:
        if not isinstance(args[0], Cycler):
            raise TypeError("If only one positional argument given, it must "
                            "be a Cycler instance.")
        return validate_cycler(args[0])
    elif len(args) == 2:
        pairs = [(args[0], args[1])]
    elif len(args) > 2:
        raise _api.nargs_error('cycler', '0-2', len(args))
    else:
        pairs = kwargs.items()

    validated = []
    for prop, vals in pairs:
        norm_prop = _prop_aliases.get(prop, prop)
        validator = _prop_validators.get(norm_prop, None)
        if validator is None:

View on GitHub (pinned to b379c1b69e)

Solutions

  1. Pass at least one property, e.g. cycler(color=['r','g','b'])
  2. Guard dynamic construction: only build a cycler when the dict is non-empty, otherwise keep the default rcParams['axes.prop_cycle']
  3. Log or assert on empty config before calling cycler(**cfg)

Example fix

# before
mpl.rcParams['axes.prop_cycle'] = cycler(**user_cycle_cfg)  # user_cycle_cfg == {}
# after
if user_cycle_cfg:
    mpl.rcParams['axes.prop_cycle'] = cycler(**user_cycle_cfg)
Defensive patterns

Strategy: validation

Validate before calling

mpl.rcParams['axes.prop_cycle'] = cycler(**cfg) if cfg else mpl.rcParams['axes.prop_cycle']

Type guard

def has_cycle_properties(cfg):
    return len(cfg) > 0

Try / catch

try:
    cyc = cycler(**cfg)
except TypeError as e:
    if 'must have positional OR keyword' in str(e):
        cyc = cycler(color=['tab:blue'])  # sane default
    else:
        raise

Prevention

When it happens

Trigger: cycler(); cycler(*[], **{}); dynamically built argument dicts that turn out empty, e.g. cycler(**cycle_dict) where cycle_dict == {}.

Common situations: Building prop_cycle kwargs programmatically from a config dict or user input that is empty; refactoring leaves a placeholder cycler() call; a helper function that forwards **kwargs which contain nothing.

Related errors


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