langchain-ai/deepagents · error · ExtensionError
Shutdown hook is not callable
Error message
Shutdown hook is not callable
What it means
Raised by ExtensionApi.on_shutdown when the registered teardown hook is not callable. Shutdown hooks are invoked deterministically at session teardown, so the library requires an actual callable before accepting it.
Solutions
- Pass the callable itself, not the result of calling it: on_shutdown(cleanup) not on_shutdown(cleanup())
- Check that the hook variable is not None (e.g. an optional callback that defaulted to None)
- Wrap non-callable teardown logic in a function before registering it
Example fix
// before ext.on_shutdown(connection.close()) // after ext.on_shutdown(lambda: connection.close())
Defensive patterns
Strategy: type-guard
Validate before calling
if not callable(hook):
raise TypeError("shutdown hook must be callable") Type guard
from collections.abc import Callable
def is_shutdown_hook(hook: object) -> bool:
return callable(hook) Try / catch
try:
ext.on_shutdown(hook)
except ExtensionError as exc:
logger.error("shutdown hook rejected: %s", exc) Prevention
- Register the function itself, never the result of calling it
- Type-annotate hook parameters as Callable[[], Any] to catch mistakes early
- Beware optional hooks: check for None before registering
When it happens
Trigger: Calling `ext.on_shutdown(obj)` where obj is None, a string, a lambda result that was invoked (None), or any non-callable value; passing the result of a function instead of the function itself.
Common situations: Writing on_shutdown(cleanup()) instead of on_shutdown(cleanup); typo'd attribute that resolved to None; passing a constant or config value instead of the callback.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Backend route got , which is not a BackendProtocol
- Registered middleware must be an AgentMiddleware, got
- ' ' is not a BaseChatModel subclass (got )
- Could not construct middleware
- Could not convert into a tool
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/2686240b5c4800e1.
Report an issue: GitHub.
Appendix: source
Thrown at libs/code/deepagents_code/extensions/api.py:187
f"Backend route {prefix!r} got {type(backend).__name__}, "
"which is not a BackendProtocol"
)
raise ExtensionError(msg)
self._registry.add_backend_route(prefix, backend, self._source)
def on_shutdown(self, hook: Callable[[], Any]) -> None:
"""Register a deterministic session teardown callback.
Args:
hook: Sync or async zero-argument callback.
Raises:
ExtensionError: If `hook` is not callable.
"""
self._ensure_active()
if not callable(hook):
msg = "Shutdown hook is not callable"
raise ExtensionError(msg)
self._registry.add_shutdown_hook(hook, self._source)
View on GitHub (pinned to a1af029e6e)