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.

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.

Appendix: 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)