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

  1. Pass an actual backend instance implementing BackendProtocol, e.g. a FilesystemBackend-like object
  2. If you passed the class, instantiate it: register_backend_route('/p/', MyBackend())
  3. If using a custom backend, make sure it structurally satisfies BackendProtocol (or subclasses/registers as one)
  4. 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

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


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/ddea1d3cdaac08d8. Report an issue: GitHub.