pytest-dev/pytest · error · TypeError
ids must be a callable or an iterable
Error message
ids must be a callable or an iterable
What it means
Raised by Metafunc._validate_ids when the ids argument passed to @pytest.mark.parametrize is neither callable nor iterable. pytest first tries callable(ids); if not, it tries iter(ids); if that also fails it raises TypeError. ids must be a callable (id function), or an iterable of strings/None matching the number of parameter sets.
Source
Thrown at src/_pytest/python.py:1553
idfn,
ids_,
self.config,
nodeid=nodeid,
)
return id_maker.make_unique_parameterset_ids()
def _validate_ids(
self,
ids: Iterable[object | None],
parametersets: Sequence[ParameterSet],
) -> list[object | None]:
try:
num_ids = len(ids) # type: ignore[arg-type]
except TypeError:
try:
iter(ids)
except TypeError as e:
raise TypeError("ids must be a callable or an iterable") from e
num_ids = len(parametersets)
# num_ids == 0 is a special case: https://github.com/pytest-dev/pytest/issues/1849
if num_ids != len(parametersets) and num_ids != 0:
nodeid = self.definition.nodeid
fail(
f"In {nodeid}: {len(parametersets)} parameter sets specified, with different number of ids: {num_ids}",
pytrace=False,
)
return list(itertools.islice(ids, num_ids))
def _validate_if_using_arg_names(
self,
argnames: Sequence[str],
indirect: bool | Sequence[str],
) -> None:
"""Check if all argnames are being used, by default values, or directly/indirectly.View on GitHub (pinned to 98b357f69e)
Solutions
- Pass ids as a list/tuple of strings (one per parameter set) or a callable.
- Ensure the variable holding ids is actually a list at runtime (guard with isinstance).
- Use pytest.param(value, id='name') to attach IDs inline instead of a separate ids list.
Example fix
// before
@pytest.mark.parametrize("x", [1,2,3], ids=3)
def test_it(x): ...
// after
@pytest.mark.parametrize("x", [1,2,3], ids=["one","two","three"])
def test_it(x): ... Defensive patterns
Strategy: type-guard
Validate before calling
from collections.abc import Iterable, Callable
def valid_ids(ids):
return ids is None or callable(ids) or isinstance(ids, Iterable)
if not valid_ids(ids):
raise TypeError("ids must be callable or iterable") Type guard
from collections.abc import Iterable, Callable
from typing import Any
def is_valid_ids(v: Any) -> bool:
return v is None or callable(v) or isinstance(v, Iterable) Prevention
- Pass a list of strings or a callable for ids.
- Validate ids is a list at runtime if built dynamically.
- Use pytest.param(value, id=...) for inline IDs.
When it happens
Trigger: Passing ids=42, ids=None-in-a-non-iterable-wrapper, ids=some_object to parametrize where the object is neither callable nor iterable.
Common situations: Passing an integer or float as ids by mistake; passing a single string when a list was intended (a string IS iterable, so this case usually passes through but yields per-char ids); a variable that was expected to be a list but resolved to a scalar.
Related errors
- {nodeid}: error raised while trying to determine id of param
- Empty parameter set in '{func.__name__}' at line {lineno + 1
- pytest.param cannot add pytest.mark.usefixtures; see https:/
- Expected id to be a string or a `pytest.HIDDEN_PARAM` sentin
- invalid type for lines2: {type(lines2).__name__}
AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04).
Data as JSON: /data/errors/035517879921843a.json.
Report an issue: GitHub.