pandas-dev/pandas · error · NotImplementedError

the 'numba' engine doesn't support lists of callables yet

Error message

the 'numba' engine doesn't support lists of callables yet

What it means

Raised in `FrameApply.apply` when `func` is list-like AND `engine='numba'`. Even though each individual list entry might be a valid callable, the numba engine does not implement multi-callable dispatch — only a single callable is supported. Distinct from error 69 (which fires in `apply_list_or_dict_like`); this check guards the early dispatch in `FrameApply.apply`.

Source

Thrown at pandas/core/apply.py:1015

    @property
    def res_columns(self) -> Index:
        return self.result_columns

    @property
    def columns(self) -> Index:
        return self.obj.columns

    @cache_readonly
    def values(self):
        return self.obj.values

    def apply(self) -> DataFrame | Series:
        """compute the results"""

        # dispatch to handle list-like or dict-like
        if is_list_like(self.func):
            if self.engine == "numba":
                raise NotImplementedError(
                    "the 'numba' engine doesn't support lists of callables yet"
                )
            return self.apply_list_or_dict_like()

        # all empty
        if len(self.columns) == 0 and len(self.index) == 0:
            return self.apply_empty_result()

        # string dispatch
        if isinstance(self.func, str):
            if self.engine == "numba":
                raise NotImplementedError(
                    "the 'numba' engine doesn't support using "
                    "a string as the callable function"
                )
            return self.apply_str()

        # ufunc

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Use the default python engine for list-of-callables: `df.apply([f1, f2])`.
  2. Invoke numba per callable separately: `[df.apply(f, engine='numba', raw=True) for f in [f1, f2]]`.
  3. Combine the callables into a single function returning a tuple/array if you need one numba pass.

Example fix

# before
df.apply([f1, f2], engine='numba')
# after
[df.apply(f, engine='numba', raw=True) for f in [f1, f2]]
Defensive patterns

Strategy: validation

Validate before calling

def safe_apply_numba(df, func, engine='python', **kw):
    import collections.abc
    if engine == 'numba' and isinstance(func, (list, tuple)):
        raise ValueError('numba engine does not support list of callables')
    return df.apply(func, engine=engine, **kw)

Type guard

def is_numba_compatible(func, engine) -> bool:
    import collections.abc
    return engine != 'numba' or (callable(func) and not isinstance(func, (list, tuple, str)))

Try / catch

try:
    df.apply(funcs, engine='numba')
except NotImplementedError as e:
    if 'lists of callables' in str(e):
        [df.apply(f, engine='numba', raw=True) for f in funcs]
    else:
        raise

Prevention

When it happens

Trigger: `df.apply([f1, f2], engine='numba')` — list of callables. The check at apply.py:1014 fires before any dispatch.

Common situations: Passing a list of callables expecting numba to JIT each; copy-paste of engine='numba' from a single-callable call into a list call; refactoring that wraps a single callable into a list.

Related errors


AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07). Data as JSON: /api/errors/048aee309434cd6c. Report an issue: GitHub.