zylon-ai/private-gpt · error · TypeError

{path!r} is not a ToolEventAdapter subclass

Error message

{path!r} is not a ToolEventAdapter subclass

What it means

Raised by load_tool_event_adapter_class when a ToolSpec's event_adapter import path ('module.qualname:Class.Path') resolves to an object that is either not a class or not a subclass of ToolEventAdapter. The registry dynamically imports the module, walks the dotted qualname via getattr, then type-checks the result.

Source

Thrown at private_gpt/components/tools/events/registry.py:24

from private_gpt.components.tools.events.adapters import (
    ClientToolEventAdapter,
    ServerToolEventAdapter,
    ToolEventAdapter,
)
from private_gpt.settings.settings import settings

if TYPE_CHECKING:
    from private_gpt.components.chat.models.chat_config_models import ToolSpec


def load_tool_event_adapter_class(path: str) -> type[ToolEventAdapter]:
    module_name, qualname = path.split(":", maxsplit=1)
    module = importlib.import_module(module_name)
    resolved: object = module
    for attribute in qualname.split("."):
        resolved = getattr(resolved, attribute)
    if not isinstance(resolved, type) or not issubclass(resolved, ToolEventAdapter):
        raise TypeError(f"{path!r} is not a ToolEventAdapter subclass")
    return resolved


def resolve_tool_event_adapter(tool_spec: ToolSpec) -> ToolEventAdapter:
    mode = settings().code_execution.tools.server_tool_result_mode
    if mode == "client":
        return ClientToolEventAdapter()
    adapter_cls = tool_spec.event_adapter
    if adapter_cls is None:
        return (
            ServerToolEventAdapter()
            if tool_spec.runtime == "server"
            else ClientToolEventAdapter()
        )
    return adapter_cls()

View on GitHub (pinned to 4a030776a3)

Solutions

  1. Make the referenced class explicitly inherit from ToolEventAdapter (from private_gpt.components.tools.events.registry or its defining module)
  2. Fix the 'module:qualname' string: exact module path, exact class name, no trailing whitespace
  3. If the class moved, update the string to the new module/qualname
  4. Verify in a REPL: import the module and assert issubclass(target, ToolEventAdapter)

Example fix

# before
tool_spec.event_adapter = "my_pkg.adapters:my_adapter_instance"
# after
from private_gpt.components.tools.events.registry import ToolEventAdapter

class MyAdapter(ToolEventAdapter):
    ...

tool_spec.event_adapter = "my_pkg.adapters:MyAdapter"
Defensive patterns

Strategy: type-guard

Validate before calling

import importlib
from private_gpt.components.tools.events.registry import ToolEventAdapter

def is_valid_adapter_path(path: str) -> bool:
    try:
        module_name, qualname = path.split(":", maxsplit=1)
        resolved = importlib.import_module(module_name)
        for attr in qualname.split("."):
            resolved = getattr(resolved, attr)
    except (ValueError, ImportError, AttributeError):
        return False
    return isinstance(resolved, type) and issubclass(resolved, ToolEventAdapter)

Type guard

from private_gpt.components.tools.events.registry import ToolEventAdapter

def is_tool_event_adapter_cls(obj: object) -> bool:
    return isinstance(obj, type) and issubclass(obj, ToolEventAdapter) and obj is not ToolEventAdapter

Try / catch

try:
    adapter_cls = load_tool_event_adapter_class(path)
except (TypeError, ImportError, AttributeError) as e:
    raise ConfigurationError(f"bad event_adapter {path!r}: {e}") from e

Prevention

When it happens

Trigger: Setting tool_spec.event_adapter to a path like 'my_pkg.adapters:MyAdapter' where MyAdapter does not inherit from ToolEventAdapter, points to a function/instance instead of a class, contains a typo in module or attribute name (raises AttributeError/ModuleNotFoundError first), or the class was moved/renamed between versions.

Common situations: Custom event adapters registered by string in tool specs or config; refactoring that renamed a class without updating the adapter path string; importing an abstract base or a mixin that never subclassed ToolEventAdapter.

Related errors


AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15). Data as JSON: /api/errors/4632d82265095502. Report an issue: GitHub.