sgl-project/sglang · error · TypeError

{spec_class.__name__} is missing duck-typed methods from Spe

Error message

{spec_class.__name__} is missing duck-typed methods from SpeculativeAlgorithm: {missing}. Add them to {spec_class.__name__} so plugin-registered algorithms stay dispatchable.

What it means

Plugin-registered algorithms are duck-typed against SpeculativeAlgorithm: any is_*() / supports_*() predicate defined on the enum must exist on the custom spec class so dispatch code can call it uniformly. register_algorithm runs _assert_custom_spec_algo_conforms and raises TypeError listing the missing names.

Source

Thrown at python/sglang/srt/speculative/spec_registry.py:218

    Called from ``register_algorithm`` rather than at import time because
    ``spec_info`` imports this module, so ``SpeculativeAlgorithm`` does not yet
    exist while this module is loading; at registration time it is fully
    defined.
    """
    # NOTE: use ``vars()`` not ``dir()`` for the enum — ``EnumMeta.__dir__``
    # hides instance methods, so ``dir(SpeculativeAlgorithm)`` would yield an
    # empty interface and turn this guard into a silent no-op.
    from sglang.srt.speculative.spec_info import SpeculativeAlgorithm

    interface = {
        name
        for name in vars(SpeculativeAlgorithm)
        if name.startswith(("is_", "supports_"))
    }
    missing = sorted(interface - set(dir(spec_class)))
    if missing:
        raise TypeError(
            f"{spec_class.__name__} is missing duck-typed methods from "
            f"SpeculativeAlgorithm: {missing}. Add them to {spec_class.__name__} "
            "so plugin-registered algorithms stay dispatchable."
        )


def register_algorithm(
    name: str,
    *,
    supports_overlap: bool = False,
    validate_server_args: Optional[ServerArgsValidator] = None,
    spec_class: Type[CustomSpecAlgo] = CustomSpecAlgo,
) -> Callable[[WorkerFactory], WorkerFactory]:
    """Return a decorator that registers a plugin algorithm under ``name``.

    Pass a ``spec_class`` subclass of ``CustomSpecAlgo`` to override any
    ``is_*()`` / ``supports_*()`` / ``create_worker`` method.
    """

View on GitHub (pinned to 0132848349)

Solutions

  1. Add the listed missing methods (usually returning False) to your spec class
  2. Alternatively inherit from a conforming base like CustomSpecAlgo's latest version that provides defaults
  3. Pin/align your plugin with the SGLang version that added the predicates

Example fix

# before
class MyAlgo(CustomSpecAlgo):
    ...
# after
class MyAlgo(CustomSpecAlgo):
    def supports_overlap(self) -> bool:
        return False
    def is_eagle(self) -> bool:
        return False
Defensive patterns

Strategy: type-guard

Validate before calling

required = {n for n in vars(SpeculativeAlgorithm) if n.startswith(('is_','supports_'))}
missing = sorted(required - set(dir(MyAlgo)))
assert not missing, missing

Type guard

def conforms(spec_class: type) -> bool:
    required = {n for n in vars(SpeculativeAlgorithm) if n.startswith(('is_','supports_'))}
    return not (required - set(dir(spec_class)))

Prevention

When it happens

Trigger: Calling register_algorithm with a CustomSpecAlgo subclass that does not define (or inherit) one of the is_*/supports_* predicates added to SpeculativeAlgorithm — commonly after upgrading SGLang when new predicates were added to the interface.

Common situations: Version upgrades adding new predicates (e.g. supports_overlap, is_eagle) break older plugin classes; hand-written spec classes missing methods.

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/d9010e1318b3a489. Report an issue: GitHub.