deepset-ai/haystack · error
A FunctionHook requires at least one of `function` or `async
Error message
A FunctionHook requires at least one of `function` or `async_function` to be set.
What it means
FunctionHook wraps a sync and/or async callable and raises ValueError in __init__ (haystack/hooks/from_function.py:50) when neither function nor async_function is provided. A hook with no callable would have no behavior to run, so construction fails immediately.
Source
Thrown at haystack/hooks/from_function.py:50
"""
def __init__(
self,
function: Callable[[State], None] | None = None,
async_function: Callable[[State], Awaitable[None]] | None = None,
) -> None:
"""
Initialize the hook with a synchronous function, an async function, or both.
:param function: The synchronous function invoked by `run`. Must be a regular function — coroutine functions
should be passed to `async_function` instead. Either `function` or `async_function` (or both) must be set.
:param async_function: Optional coroutine function awaited by `run_async`. When only `async_function` is set,
`run` raises a `RuntimeError`. When only `function` is set, `run_async` calls `function`.
:raises ValueError: If neither is set, if `function` is a coroutine function, if `async_function` is not, or
if a provided function does not declare a `State`-typed parameter.
"""
if function is None and async_function is None:
raise ValueError("A FunctionHook requires at least one of `function` or `async_function` to be set.")
if function is not None and inspect.iscoroutinefunction(function):
raise ValueError(
f"`function` must be a synchronous function. '{function.__name__}' is a coroutine function. "
"Pass it as `async_function` instead."
)
if async_function is not None and not inspect.iscoroutinefunction(async_function):
raise ValueError(
f"`async_function` must be a coroutine function defined with `async def`. "
f"Got '{getattr(async_function, '__name__', repr(async_function))}'."
)
for func in (function, async_function):
if func is not None and not _takes_single_state_argument(func):
raise ValueError(
f"Hook function '{func.__name__}' must take a single parameter annotated with `State` "
"(e.g. `def my_hook(state: State) -> None`)."
)
self.function = function
self.async_function = async_functionView on GitHub (pinned to e318778c9b)
Solutions
- Pass at least one callable: FunctionHook(function=my_sync_fn) or FunctionHook(async_function=my_async_fn).
- Check why the variable holding the function is None (import failure, wrong name).
- Guard at the call site: assert callable(fn) before constructing.
Example fix
// before hook = FunctionHook() # both None // after hook = FunctionHook(function=my_sync_fn, async_function=my_async_fn)
Defensive patterns
Strategy: validation
Validate before calling
def make_function_hook(fn=None, async_fn=None):
if fn is None and async_fn is None:
raise ValueError("provide function and/or async_function")
return FunctionHook(function=fn, async_function=async_fn) Type guard
def is_callable_or_none(f) -> bool:
return f is None or callable(f) Try / catch
try:
hook = FunctionHook(function=fn, async_function=afn)
except ValueError as e:
if "at least one of" in str(e):
logger.error("FunctionHook built with no callable; check wiring of %r/%r", fn, afn)
raise
raise Prevention
- Never construct FunctionHook with variables that may be None
- Import and smoke-test the wrapped function before wiring the hook
- Assert callable(fn) at pipeline assembly time
- Prefer explicit keyword arguments to avoid dropped positional args
When it happens
Trigger: FunctionHook() with both arguments None/omitted; passing a variable that is None at call time; conditionally assigning the callable and having the condition fail.
Common situations: Refactoring where the callable was deleted or renamed; loading a hook spec from config where the function reference didn't resolve; typos so the kwarg never receives the function.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- `context_window` must be a positive number of tokens, got {c
- `compact_at` and `compact_to` must satisfy 0 < compact_to <
- `min_keep_steps` must be at least 0, got {min_keep_steps}.
- `min_keep_steps` must be at least 0, got {min_keep_steps}.
- `approximate_summary_tokens` must be a positive number of to
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/861480a5648ceb7a.
Report an issue: GitHub.