python/cpython · error · TypeError

issubclass() arg 1 must be a class

Error message

issubclass() arg 1 must be a class

What it means

Raised by ABCMeta.__subclasscheck__ (pure-Python _py_abc fallback; the C _abc raises the equivalent) when issubclass() is called with a first argument that is not a class. ABCs implement duck-typed virtual subclass checks that only make sense for classes, so issubclass(instance, MyABC) fails fast with TypeError instead of guessing.

Source

Thrown at Lib/_py_abc.py:111

        """Override for isinstance(instance, cls)."""
        # Inline the cache checking
        subclass = instance.__class__
        if subclass in cls._abc_cache:
            return True
        subtype = type(instance)
        if subtype is subclass:
            if (cls._abc_negative_cache_version ==
                ABCMeta._abc_invalidation_counter and
                subclass in cls._abc_negative_cache):
                return False
            # Fall back to the subclass check.
            return cls.__subclasscheck__(subclass)
        return any(cls.__subclasscheck__(c) for c in (subclass, subtype))

    def __subclasscheck__(cls, subclass):
        """Override for issubclass(subclass, cls)."""
        if not isinstance(subclass, type):
            raise TypeError('issubclass() arg 1 must be a class')
        # Check cache
        if subclass in cls._abc_cache:
            return True
        # Check negative cache; may have to invalidate
        if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter:
            # Invalidate the negative cache
            cls._abc_negative_cache = WeakSet()
            cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
        elif subclass in cls._abc_negative_cache:
            return False
        # Check the subclass hook
        ok = cls.__subclasshook__(subclass)
        if ok is not NotImplemented:
            assert isinstance(ok, bool)
            if ok:
                cls._abc_cache.add(subclass)
            else:
                cls._abc_negative_cache.add(subclass)

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Use isinstance(obj, MyABC) when checking an instance
  2. Branch on the argument kind: issubclass(x, MyABC) if isinstance(x, type) else isinstance(x, MyABC)
  3. Validate external input before passing it to issubclass

Example fix

# before
issubclass(widget, Drawable)   # widget is an instance -> TypeError

# after
isinstance(widget, Drawable)    # instance check
# or, for either kind:
isinstance(widget, Drawable) if not isinstance(widget, type) else issubclass(widget, Drawable)
Defensive patterns

Strategy: type-guard

Validate before calling

def is_a(obj, abc) -> bool:
    """Works for both instances and classes."""
    if isinstance(obj, type):
        return issubclass(obj, abc)
    return isinstance(obj, abc)

Type guard

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

Prevention

When it happens

Trigger: issubclass(obj, MyABC) where obj is an instance; passing a non-type (module, function, mock) to issubclass against any ABC; custom code that forwards user input into issubclass without checking it is a type. isinstance(instance, MyABC) does NOT raise — the error only comes from the issubclass path.

Common situations: Generic helper functions that want to accept 'class or instance' and call issubclass unconditionally; copy/paste swapping isinstance/issubclass; serialization frameworks dispatching on either a class or an instance; tests probing ABCs with fixtures.

Related errors


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