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
- Make the referenced class explicitly inherit from ToolEventAdapter (from private_gpt.components.tools.events.registry or its defining module)
- Fix the 'module:qualname' string: exact module path, exact class name, no trailing whitespace
- If the class moved, update the string to the new module/qualname
- 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
- Define adapter paths as constants next to the classes they name, never as free-form config strings
- Add a startup check that validates every registered event_adapter path via the same import logic
- Run issubclass checks in unit tests for custom adapters
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
- Code execution provider '{name}' is not registered. Availabl
- Unsupported semaphore mode: {mode!r}. Available: {', '.join(
- Embedding mode '{mode}' is not supported. Available: {availa
- Invalid reasoning_effort budget: {budget}. Must be a number
- LLM mode '{mode}' is not supported. Available: {available}
AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15).
Data as JSON: /api/errors/4632d82265095502.
Report an issue: GitHub.