docling-project/docling · error · ValueError
{opt_type.kind!r} already registered to class {self._classes
Error message
{opt_type.kind!r} already registered to class {self._classes[opt_type]!r} What it means
Raised as ValueError by BaseFactory.register when a plugin tries to register an options type that is already mapped to a class. The factory enforces one implementation class per options type to keep resolution deterministic.
Source
Thrown at docling/models/factories/base_factory.py:81
if opt_cls.kind == kind:
return opt_cls(*args, **kwargs)
raise RuntimeError(self._err_msg_on_class_not_found(kind))
def _err_msg_on_class_not_found(self, kind: str):
msg = []
for opt, cls in self._classes.items():
msg.append(f"\t{opt.kind!r} => {cls!r}")
msg_str = "\n".join(msg)
return f"No class found with the name {kind!r}, known classes are:\n{msg_str}"
def register(self, cls: Type[A], plugin_name: str, plugin_module_name: str):
opt_type = cls.get_options_type()
if opt_type in self._classes:
raise ValueError(
f"{opt_type.kind!r} already registered to class {self._classes[opt_type]!r}"
)
self._classes[opt_type] = cls
self._meta[opt_type] = FactoryMeta(
kind=opt_type.kind, plugin_name=plugin_name, module=plugin_module_name
)
def load_from_plugins(
self, plugin_name: Optional[str] = None, allow_external_plugins: bool = False
):
plugin_name = plugin_name or self.plugin_name
plugin_manager = PluginManager(plugin_name)
plugin_manager.load_setuptools_entrypoints(plugin_name)
for plugin_name, plugin_module in plugin_manager.list_name_plugin():
plugin_module_name = str(plugin_module.__name__) # type: ignoreView on GitHub (pinned to 61d76f1ff3)
Solutions
- Make the plugin idempotent: check `opt_type in factory.classes` before calling register, or guard registration behind a module-level flag.
- Give your plugin its own distinct options subclass with a unique kind instead of reusing an existing options class.
- Remove the duplicate import/registration path (e.g. registering both via entry point and via explicit import).
Example fix
# before
class MyModel(BaseModel):
...
factory.register(MyModel, 'my_plugin', 'my_plugin.models') # ValueError if re-imported
# after
if MyModel.get_options_type() not in factory.classes:
factory.register(MyModel, 'my_plugin', 'my_plugin.models') Defensive patterns
Strategy: validation
Validate before calling
opt_type = MyModel.get_options_type()
if opt_type in factory.classes:
print(f'skip: {opt_type.kind!r} already registered to {factory.classes[opt_type]!r}')
else:
factory.register(MyModel, 'my_plugin', 'my_plugin.models') Type guard
def needs_registration(factory, cls) -> bool:
return cls.get_options_type() not in factory.classes Try / catch
try:
factory.register(cls, plugin_name, module_name)
except ValueError as e:
if 'already registered' in str(e):
pass # idempotent plugin load
else:
raise Prevention
- Make plugin registration idempotent (check factory.classes first).
- Register each options type exactly once — give plugins their own options subclass.
- Avoid importing the same plugin via two module paths.
When it happens
Trigger: Registering two classes whose get_options_type() returns the same options class — e.g. a plugin re-registers a class already registered by docling-core, or two plugins vendored/duplicated copies of the same options class.
Common situations: Developing a plugin that subclasses or re-imports an existing options class and calls register() again; double import of a plugin under different module names; running registration both at import time and explicitly.
Related errors
- No class found with the name {kind!r}, known classes are: {m
- Expected OnnxRuntimeImageClassificationEngineOptions, got {t
- Expected TransformersImageClassificationEngineOptions, got {
- Expected ApiKserveV2ImageClassificationEngineOptions, got {t
- Unknown engine type: {options.engine_type}
AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14).
Data as JSON: /api/errors/741d0df8824a6a37.
Report an issue: GitHub.