sqlalchemy/alembic · error · ValueError
no dispatch function for object: %s
Error message
no dispatch function for object: %s
What it means
Raised as ValueError by Dispatcher.dispatch (langhelpers.py:340) when, after walking the object's MRO (and any fallback qualifiers), no registered function matches any class in the hierarchy. The dispatcher is a type-keyed lookup table; a miss means no handler was ever registered for that type or any of its bases.
Source
Thrown at alembic/util/langhelpers.py:340
def dispatch(self, obj: Any, qualifier: str = "default") -> Any:
if isinstance(obj, str):
targets: Sequence[Any] = [obj]
elif isinstance(obj, type):
targets = obj.__mro__
else:
targets = type(obj).__mro__
if qualifier != "default":
qualifiers = [qualifier, "default"]
else:
qualifiers = ["default"]
for spcls in targets:
for qualifier in qualifiers:
if (spcls, qualifier) in self._registry:
return self._registry[(spcls, qualifier)]
else:
raise ValueError("no dispatch function for object: %s" % obj)
def branch(self) -> Dispatcher:
"""Return a copy of this dispatcher that is independently
writable."""
d = Dispatcher()
d._registry.update(self._registry)
return d
class PriorityDispatcher:
"""registers lists of functions at multiple levels of priority and provides
a target to invoke them in priority order.
.. versionadded:: 1.18.0 - PriorityDispatcher replaces the job
of Dispatcher(uselist=True)
"""View on GitHub (pinned to 44fb345033)
Solutions
- Register a dispatch function for the type (or a common base) before calling dispatch: dispatcher.dispatch_for(MyType)(fn).
- Upgrade Alembic to a version that supports the construct type produced by your SQLAlchemy version.
- Check whether the object's type is what you expect (print type(obj).__mro__) — a wrapper/proxy may hide the real type.
- If writing a custom impl, cover the type via dispatch_for on the base class so subclasses resolve too.
Example fix
# before: no handler registered for MyType
dispatcher.dispatch(my_obj) # ValueError: no dispatch function
# after: register first
@dispatcher.dispatch_for(MyType)
def handle_my_type(obj):
...
dispatcher.dispatch(my_obj) Defensive patterns
Strategy: validation
Validate before calling
from alembic.util.langhelpers import Dispatcher
def has_handler(d: Dispatcher, obj) -> bool:
targets = [obj] if isinstance(obj, str) else (obj.__mro__ if isinstance(obj, type) else type(obj).__mro__)
return any((t, 'default') in d._registry for t in targets)
if not has_handler(d, my_obj):
raise SystemExit(f'No dispatch handler for {type(my_obj)}; register one first') Try / catch
try:
result = dispatcher.dispatch(obj)
except ValueError as e:
if 'no dispatch function' in str(e):
# register a fallback for the base type, then retry
dispatcher.dispatch_for(type(obj))(lambda x: None)
result = dispatcher.dispatch(obj)
else:
raise Prevention
- Register handlers for base classes so unknown subclasses still resolve.
- Upgrade Alembic alongside SQLAlchemy so new construct types are covered.
- In custom impls, log type(obj).__mro__ when dispatch fails to diagnose gaps.
When it happens
Trigger: Calling dispatcher.dispatch(obj) for an object whose type (and all superclasses) have no entry; querying a fresh/empty dispatcher; passing a primitive type (int, str) to a dispatcher that only handles SQLAlchemy construct types.
Common situations: An autogenerate comparison passes an unsupported SQL construct type to a dispatcher that has no impl for it; a custom dialect/impl that did not register handlers for a type autogenerate encounters; upgrading SQLAlchemy which introduces a new construct subclass not yet handled by the Alembic version in use.
Related errors
- Can not set dispatch function for object {target!r}: key alr
- revision %s not in map
- Don't know how to comma-format %r
- Can't drop table in batch mode
- Constraint must have a name
AI-assisted analysis of sqlalchemy/alembic@44fb345033 (2026-08-04).
Data as JSON: /data/errors/ef145b44511390ae.json.
Report an issue: GitHub.