pytest-dev/pytest · error · TypeError

Expected , but got an exception instance

Error message

Expected {expected}, but got an exception instance: {type(exc).__name__}

What it means

Raised by RaisesExc._parse_exc when an exception INSTANCE is passed where a TYPE is expected. pytest.raises/RaisesExc accept classes (or group generics), not instances like ValueError('x'). The TypeError reports the actual instance type so the caller sees the mismatch.

Solutions

  1. Pass the class: pytest.raises(ValueError) instead of pytest.raises(ValueError('boom')).
  2. If asserting on message, use the match= argument: pytest.raises(ValueError, match='boom').
  3. When the value comes from excinfo, use type(excinfo.value).

Example fix

// before
with pytest.raises(ValueError('boom')):
    ...
// after
with pytest.raises(ValueError, match='boom'):
    ...
Defensive patterns

Strategy: type-guard

Validate before calling

assert not isinstance(exc, BaseException), f'pass the exception class, not an instance: {type(exc).__name__}'

Type guard

def is_exception_class_not_instance(exc) -> bool:
    return isinstance(exc, type) and not isinstance(exc, BaseException)

Prevention

When it happens

Trigger: pytest.raises(ValueError('boom')), RaisesExc(RuntimeError('x')), or passing excinfo.value (an instance) instead of type(excinfo.value). Fires on the isinstance(exc, BaseException) branch after the type branch.

Common situations: Copy-paste from a raise ValueError('x') line into raises(...); passing a caught exception instance through a variable; beginners assuming raises mirrors raise syntax.

Related errors


AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11). Data as JSON: /api/errors/8a3ca6facf5608bd. Report an issue: GitHub.

Appendix: source

Thrown at src/_pytest/raises.py:453

                and exc_type in (BaseException, Any)
            ):
                if not issubclass(origin_exc, ExceptionGroup):
                    self.is_baseexception = True
                return cast(type[BaseExcT_1], origin_exc)
            else:
                raise ValueError(
                    f"Only `ExceptionGroup[Exception]` or `BaseExceptionGroup[BaseException]` "
                    f"are accepted as generic types but got `{exc}`. "
                    f"As `raises` will catch all instances of the specified group regardless of the "
                    f"generic argument specific nested exceptions has to be checked "
                    f"with `RaisesGroup`."
                )
        # unclear if the Type/ValueError distinction is even helpful here
        msg = f"Expected {expected}, but got "
        if isinstance(exc, type):  # type: ignore[unreachable]
            raise ValueError(msg + f"{exc.__name__!r}")
        if isinstance(exc, BaseException):  # type: ignore[unreachable]
            raise TypeError(msg + f"an exception instance: {type(exc).__name__}")
        raise TypeError(msg + repr(type(exc).__name__))

    @property
    def fail_reason(self) -> str | None:
        """Set after a call to :meth:`matches` to give a human-readable reason for why the match failed.
        When used as a context manager the string will be printed as the reason for the
        test failing."""
        return self._fail_reason

    def _check_check(
        self: AbstractRaises[BaseExcT_1],
        exception: BaseExcT_1,
    ) -> bool:
        if self.check is None:
            return True

        if self.check(exception):
            return True

View on GitHub (pinned to 0d6fbdeffa)