pytest-dev/pytest · error · ValueError
You cannot specify multiple exceptions with…
Error message
You cannot specify multiple exceptions with `allow_unwrapped=True.` If you want to match one of multiple possible exceptions you should use a `RaisesExc`. E.g. `RaisesExc(check=lambda e: isinstance(e, (...)))`
What it means
Raised by RaisesGroup.__init__ when allow_unwrapped=True is combined with more than one expected exception (the other_exceptions branch). allow_unwrapped means the matcher will accept a single non-group exception by wrapping it implicitly; with multiple candidate types that single exception could not be disambiguated. pytest steers users to RaisesExc(check=lambda e: isinstance(e, (...))) for 'one of several' matching.
Solutions
- Drop allow_unwrapped and let the exception arrive already wrapped in an ExceptionGroup.
- Keep allow_unwrapped=True but expect a single type, and move multi-type matching into a check: RaisesExc(check=lambda e: isinstance(e, (ValueError, KeyError))).
- Wrap the group matcher so it accepts either shape via a custom check on RaisesGroup itself.
Example fix
// before
with pytest.raises(RaisesGroup(ValueError, KeyError, allow_unwrapped=True)):
...
// after
with pytest.raises(RaisesExc(check=lambda e: isinstance(e, (ValueError, KeyError)))):
... Defensive patterns
Strategy: validation
Validate before calling
n = 0 if expected_exception is None else (len(expected_exception) if isinstance(expected_exception, tuple) else 1) n += len(other_exceptions) assert not (allow_unwrapped and n > 1), 'allow_unwrapped=True requires exactly one expected exception'
Type guard
def raisesgroup_unwrapped_single(expected_exception, other_exceptions, allow_unwrapped) -> bool:
n = 0 if expected_exception is None else (len(expected_exception) if isinstance(expected_exception, tuple) else 1)
n += len(other_exceptions or ())
return (not allow_unwrapped) or n <= 1 Prevention
- Reserve allow_unwrapped=True for single-type RaisesGroup usage.
- Use RaisesExc(check=lambda e: isinstance(e, (...))) for 'one of several' matching.
- Document the convention in your group-matcher helpers.
When it happens
Trigger: RaisesGroup(ValueError, KeyError, allow_unwrapped=True); RaisesGroup((ValueError, KeyError), allow_unwrapped=True); or any RaisesGroup where other_exceptions is non-empty and allow_unwrapped is set.
Common situations: Adapting a RaisesGroup to also accept a lone exception (unwrapped) while still wanting to match a set of candidate types; migrating from raises(ValueError, KeyError) to group semantics.
Related errors
- `allow_unwrapped=True` bypasses the `match` and `check`…
- `allow_unwrapped=True` has no effect when expecting a…
- Expected , but got . RaisesGroup does not support tuples of…
- You cannot specify a nested structure inside a RaisesGroup…
- Only `ExceptionGroup[Exception]` or…
AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11).
Data as JSON: /api/errors/26c59368930b4c34.
Report an issue: GitHub.
Appendix: source
Thrown at src/_pytest/raises.py:971
Callable[[BaseExceptionGroup[BaseExcT_1]], bool]
| Callable[[ExceptionGroup[ExcT_1]], bool]
| None
) = None,
):
# The type hint on the `self` and `check` parameters uses different formats
# that are *very* hard to reconcile while adhering to the overloads, so we cast
# it to avoid an error when passing it to super().__init__
check = cast(
"Callable[[BaseExceptionGroup[ExcT_1|BaseExcT_1|BaseExceptionGroup[BaseExcT_2]]], bool]",
check,
)
super().__init__(match=match, check=check)
self.allow_unwrapped = allow_unwrapped
self.flatten_subgroups: bool = flatten_subgroups
self.is_baseexception = False
if allow_unwrapped and other_exceptions:
raise ValueError(
"You cannot specify multiple exceptions with `allow_unwrapped=True.`"
" If you want to match one of multiple possible exceptions you should"
" use a `RaisesExc`."
" E.g. `RaisesExc(check=lambda e: isinstance(e, (...)))`",
)
if allow_unwrapped and isinstance(expected_exception, RaisesGroup):
raise ValueError(
"`allow_unwrapped=True` has no effect when expecting a `RaisesGroup`."
" You might want it in the expected `RaisesGroup`, or"
" `flatten_subgroups=True` if you don't care about the structure.",
)
if allow_unwrapped and (match is not None or check is not None):
raise ValueError(
"`allow_unwrapped=True` bypasses the `match` and `check` parameters"
" if the exception is unwrapped. If you intended to match/check the"
" exception you should use a `RaisesExc` object. If you want to match/check"
" the exceptiongroup when the exception *is* wrapped you need to"
" do e.g. `if isinstance(exc.value, ExceptionGroup):"View on GitHub (pinned to 0d6fbdeffa)