D4Vinci/Scrapling · error · TypeError
Callable filter function must have at least one argument to…
Error message
Callable filter function must have at least one argument to take `Selector` objects.
What it means
A callable passed to find_all() takes zero parameters, so it cannot receive the Selector objects it is supposed to filter. scrapling inspects the callable's signature with inspect.signature and requires at least one positional parameter.
Solutions
- Add the element parameter to the callable: def keep(s): return s.attrib.get('data-ok') == '1'.
- If using functools.partial, ensure at least one positional slot remains free for the Selector.
- Note that builtins with optional-only args may also trip the signature check — wrap them in a lambda taking one argument.
Example fix
# before selector.find_all(lambda: True) # TypeError # after selector.find_all(lambda s: True)
Defensive patterns
Strategy: validation
Validate before calling
from inspect import signature
def takes_at_least_one_arg(fn) -> bool:
try:
return len(signature(fn).parameters) > 0
except (TypeError, ValueError):
return False
assert takes_at_least_one_arg(my_filter), 'filter must accept a Selector argument' Prevention
- Write filter callables as lambda s: ... from the start so the parameter is never forgotten.
- With functools.partial, leave at least one positional parameter unfilled for the Selector.
When it happens
Trigger: find_all(lambda: True) or find_all(some_zero_arg_function). Lambdas with one arg like lambda s: s.attrib.get('x') are fine.
Common situations: Refactoring a filter from a constant-returning helper; passing a functools.partial that consumed all positional arguments; passing a class's __init__-less instance method bound with no free parameters left.
Related errors
- Argument with type " " is not accepted, please read the…
- Nested dictionaries are not accepted, only string keys and…
- Nested Iterables are not accepted, only iterables of tag…
- Only string values are accepted for arguments
- strategy must be callable, got
AI-assisted analysis of D4Vinci/Scrapling@5d213a2d47 (2026-08-14).
Data as JSON: /api/errors/37b6ae2a22313df0.
Report an issue: GitHub.
Appendix: source
Thrown at scrapling/parser.py:743
if not all(map(lambda x: isinstance(x, str), arg)):
raise TypeError("Nested Iterables are not accepted, only iterables of tag names are accepted")
tags.update(set(arg))
elif isinstance(arg, dict):
if not all([(isinstance(k, str) and isinstance(v, str)) for k, v in arg.items()]):
raise TypeError(
"Nested dictionaries are not accepted, only string keys and string values are accepted"
)
attributes.update(arg)
elif isinstance(arg, re_Pattern):
patterns.add(arg)
elif callable(arg):
if len(signature(arg).parameters) > 0:
functions.append(arg)
else:
raise TypeError(
"Callable filter function must have at least one argument to take `Selector` objects."
)
else:
raise TypeError(f'Argument with type "{type(arg)}" is not accepted, please read the docs.')
if not all([(isinstance(k, str) and isinstance(v, str)) for k, v in kwargs.items()]):
raise TypeError("Only string values are accepted for arguments")
for attribute_name, value in kwargs.items():
# Only replace names for kwargs, replacing them in dictionaries doesn't make sense
attribute_name = _whitelisted.get(attribute_name, attribute_name)
attributes[attribute_name] = value
# It's easier and faster to build a selector than traversing the tree
tags = tags or set("*")
for tag in tags:
selector = tagView on GitHub (pinned to 5d213a2d47)