python/cpython · error · TypeError

Can only register classes

Error message

Can only register classes

What it means

Raised by ABCMeta.register (pure-Python fallback in _py_abc, mirrored by the C _abc implementation) when the argument is not a class. register() exists to register an existing class as a virtual subclass of the ABC; passing an instance, a module, or any non-type object raises TypeError('Can only register classes').

Source

Thrown at Lib/_py_abc.py:60

            for name in getattr(base, "__abstractmethods__", set()):
                value = getattr(cls, name, None)
                if getattr(value, "__isabstractmethod__", False):
                    abstracts.add(name)
        cls.__abstractmethods__ = frozenset(abstracts)
        # Set up inheritance registry
        cls._abc_registry = WeakSet()
        cls._abc_cache = WeakSet()
        cls._abc_negative_cache = WeakSet()
        cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
        return cls

    def register(cls, subclass):
        """Register a virtual subclass of an ABC.

        Returns the subclass, to allow usage as a class decorator.
        """
        if not isinstance(subclass, type):
            raise TypeError("Can only register classes")
        if issubclass(subclass, cls):
            return subclass  # Already a subclass
        # Subtle: test for cycles *after* testing for "already a subclass";
        # this means we allow X.register(X) and interpret it as a no-op.
        if issubclass(cls, subclass):
            # This would create a cycle, which is bad for the algorithm below
            raise RuntimeError("Refusing to create an inheritance cycle")
        cls._abc_registry.add(subclass)
        ABCMeta._abc_invalidation_counter += 1  # Invalidate negative cache
        return subclass

    def _dump_registry(cls, file=None):
        """Debug helper to print the ABC registry."""
        print(f"Class: {cls.__module__}.{cls.__qualname__}", file=file)
        print(f"Inv. counter: {get_cache_token()}", file=file)
        for name in cls.__dict__:
            if name.startswith("_abc_"):
                value = getattr(cls, name)

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Pass the class object: MyABC.register(type(obj)) or the class name itself
  2. If the target is defined dynamically, ensure you pass the type object created by type()/metaclass calls, not an instance
  3. Guard the call: only register when isinstance(candidate, type)

Example fix

# before
from abc import ABC

class Drawable(ABC):
    pass

d = SomeShape()
Drawable.register(d)          # TypeError: Can only register classes

# after
Drawable.register(SomeShape)  # register the class
Defensive patterns

Strategy: type-guard

Validate before calling

def safe_register(abc, candidate):
    if not isinstance(candidate, type):
        raise TypeError(f'expected a class, got {candidate!r}')
    return abc.register(candidate)

Type guard

def is_class(obj) -> bool:
    return isinstance(obj, type)

Try / catch

try:
    MyABC.register(target)
except TypeError as e:
    if 'Can only register classes' in str(e):
        target = type(target)  # fall back to the instance's class
        MyABC.register(target)
    else:
        raise

Prevention

When it happens

Trigger: Calling MyABC.register(x) where isinstance(x, type) is false — e.g. registering an instance (MyABC.register(obj)), a function, or a module object instead of its class. Also happens with dynamic objects like mocks or partials passed as 'subclass'.

Common situations: Confusing registration of an instance vs its class (register(instance) instead of register(type(instance))); passing a class object stored via __class__ string; test code registering MagicMock; wrapper libraries that accept 'either class or instance' and forward blindly to register().

Related errors


AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14). Data as JSON: /api/errors/1aea51b45af91809. Report an issue: GitHub.