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
- Pass the class object: MyABC.register(type(obj)) or the class name itself
- If the target is defined dynamically, ensure you pass the type object created by type()/metaclass calls, not an instance
- 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
- Always pass the class object to ABC.register, never an instance
- In dynamic plugin loaders, gate registration on isinstance(plugin, type)
- Prefer structural checks (__subclasshook__/Protocols) when the registrant may not be a class
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
- issubclass() arg 1 must be a class
- Refusing to create an inheritance cycle
- Callable must be used as Callable[[arg, ...], result].
- Expected a list of types, an ellipsis, ParamSpec, or Concate
- Forward reference must be a string -- got {arg!r}
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/1aea51b45af91809.
Report an issue: GitHub.