{"id":"ef145b44511390ae","repo":"sqlalchemy/alembic","slug":"no-dispatch-function-for-object-s","errorCode":null,"errorMessage":"no dispatch function for object: %s","messagePattern":"no dispatch function for object: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"alembic/util/langhelpers.py","lineNumber":340,"sourceCode":"    def dispatch(self, obj: Any, qualifier: str = \"default\") -> Any:\n        if isinstance(obj, str):\n            targets: Sequence[Any] = [obj]\n        elif isinstance(obj, type):\n            targets = obj.__mro__\n        else:\n            targets = type(obj).__mro__\n\n        if qualifier != \"default\":\n            qualifiers = [qualifier, \"default\"]\n        else:\n            qualifiers = [\"default\"]\n\n        for spcls in targets:\n            for qualifier in qualifiers:\n                if (spcls, qualifier) in self._registry:\n                    return self._registry[(spcls, qualifier)]\n        else:\n            raise ValueError(\"no dispatch function for object: %s\" % obj)\n\n    def branch(self) -> Dispatcher:\n        \"\"\"Return a copy of this dispatcher that is independently\n        writable.\"\"\"\n\n        d = Dispatcher()\n        d._registry.update(self._registry)\n        return d\n\n\nclass PriorityDispatcher:\n    \"\"\"registers lists of functions at multiple levels of priority and provides\n    a target to invoke them in priority order.\n\n    .. versionadded:: 1.18.0 - PriorityDispatcher replaces the job\n       of Dispatcher(uselist=True)\n\n    \"\"\"","sourceCodeStart":322,"sourceCodeEnd":358,"githubUrl":"https://github.com/sqlalchemy/alembic/blob/44fb3450330204b222ff05135e1fbbbdb28c44db/alembic/util/langhelpers.py#L322-L358","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before: no handler registered for MyType\ndispatcher.dispatch(my_obj)  # ValueError: no dispatch function\n\n# after: register first\n@dispatcher.dispatch_for(MyType)\ndef handle_my_type(obj):\n    ...\ndispatcher.dispatch(my_obj)","handlingStrategy":"validation","validationCode":"from alembic.util.langhelpers import Dispatcher\n\ndef has_handler(d: Dispatcher, obj) -> bool:\n    targets = [obj] if isinstance(obj, str) else (obj.__mro__ if isinstance(obj, type) else type(obj).__mro__)\n    return any((t, 'default') in d._registry for t in targets)\n\nif not has_handler(d, my_obj):\n    raise SystemExit(f'No dispatch handler for {type(my_obj)}; register one first')","typeGuard":null,"tryCatchPattern":"try:\n    result = dispatcher.dispatch(obj)\nexcept ValueError as e:\n    if 'no dispatch function' in str(e):\n        # register a fallback for the base type, then retry\n        dispatcher.dispatch_for(type(obj))(lambda x: None)\n        result = dispatcher.dispatch(obj)\n    else:\n        raise","preventionTips":["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."],"tags":["alembic","dispatcher","lookup","missing-handler","internal-api"],"analyzedSha":"44fb3450330204b222ff05135e1fbbbdb28c44db","analyzedAt":"2026-08-04T19:57:10.248Z","schemaVersion":2}