langchain-ai/deepagents · error · ExtensionError
Backend route {prefix!r} got {type(backend).__name__}, which
Error message
Backend route {prefix!r} got {type(backend).__name__}, which is not a BackendProtocol What it means
Raised by ExtensionApi.register_backend_route when the backend argument is not an instance of BackendProtocol. The library type-checks the mounted object before adding the route to the registry.
Source
Thrown at libs/code/deepagents_code/extensions/api.py:172
Raises:
ExtensionError: If the prefix or backend is invalid.
"""
self._ensure_active()
from deepagents.backends.protocol import BackendProtocol
if _ROUTE_PREFIX.fullmatch(prefix) is None:
msg = (
f"Invalid backend route prefix {prefix!r}: use lowercase path "
"segments and include leading and trailing slashes"
)
raise ExtensionError(msg)
if not isinstance(backend, BackendProtocol):
msg = (
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)
Solutions
- Pass an actual backend instance implementing BackendProtocol, e.g. a FilesystemBackend-like object
- If you passed the class, instantiate it: register_backend_route('/p/', MyBackend())
- If using a custom backend, make sure it structurally satisfies BackendProtocol (or subclasses/registers as one)
- Check the traceback's type name in the message to confirm what object was actually passed
Example fix
// before
ext.register_backend_route("/data/", FilesystemBackend)
// after
ext.register_backend_route("/data/", FilesystemBackend(root="/data")) Defensive patterns
Strategy: type-guard
Validate before calling
if not isinstance(backend, BackendProtocol):
raise TypeError("register_backend_route requires a BackendProtocol instance") Type guard
def is_backend(obj: object) -> bool:
return isinstance(obj, BackendProtocol) Try / catch
try:
ext.register_backend_route(prefix, backend)
except ExtensionError as exc:
logger.error("%r is not a BackendProtocol: %s", type(backend).__name__, exc) Prevention
- Instantiate backend classes before mounting them
- Run mypy/pyright so non-protocol backends fail type checking
- Keep a single factory function that constructs protocol-compliant backends
When it happens
Trigger: Calling `ext.register_backend_route('/prefix/', obj)` where obj is a raw function, a class (not an instance), a wrapper, or any object that does not satisfy the BackendProtocol interface.
Common situations: Passing the backend class instead of an instance; passing a custom object that implements the methods duck-typed but is not registered/checked as BackendProtocol; refactors that renamed or replaced the backend object.
Understand the failure class
Background: "Wrong argument type", "must be a string", "expected Array or Prism::Scope": TypeError and ArgumentError when a library receives a value of the wrong type — this error's family across 28 libraries.
Related errors
- Registered middleware must be an AgentMiddleware, got {kind}
- Invalid backend route prefix {prefix!r}: use lowercase path
- Shutdown hook is not callable
- Extension backend route {item.name!r} from {item.source.labe
- Extension backend route {item.name!r} from {item.source.labe
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/ddea1d3cdaac08d8.
Report an issue: GitHub.