pytest-dev/pytest · error · ValueError
`allow_unwrapped=True` bypasses the `match` and `check` para
Error message
`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): assert RaisesGroup(...).matches(exc.value)` afterwards.
What it means
allow_unwrapped=True bypasses match and check on the group because, when the exception is unwrapped (not in a group), there is no group object to run match/check against. Combining them is contradictory and silently drops the match/check intent.
Source
Thrown at src/_pytest/raises.py:984
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):"
" assert RaisesGroup(...).matches(exc.value)` afterwards.",
)
self.expected_exceptions: tuple[
type[BaseExcT_co] | RaisesExc[BaseExcT_co] | RaisesGroup[BaseException], ...
] = tuple(
self._parse_excgroup(e, "a BaseException type, RaisesExc, or RaisesGroup")
for e in (
expected_exception,
*other_exceptions,
)
)
View on GitHub (pinned to 98b357f69e)
Solutions
- Move match/check onto a RaisesExc for the inner exception: RaisesGroup(RaisesExc(ValueError, match='foo'), allow_unwrapped=True).
- If you only care about the wrapped case, drop allow_unwrapped and keep match/check on the group.
- To conditionally check the group when it IS wrapped, assert afterward: if isinstance(exc.value, ExceptionGroup): assert RaisesGroup(...).matches(exc.value).
Example fix
// before RaisesGroup(ValueError, allow_unwrapped=True, match='foo') // after RaisesGroup(RaisesExc(ValueError, match='foo'), allow_unwrapped=True)
Defensive patterns
Strategy: validation
Validate before calling
if allow_unwrapped and (match is not None or check is not None):
raise ValueError('move match/check onto a RaisesExc, or drop allow_unwrapped')
RaisesGroup(expected, allow_unwrapped=allow_unwrapped, match=match, check=check) Prevention
- Never combine allow_unwrapped with group-level match/check.
- Push match/check into a RaisesExc for the inner exception instead.
- If you need conditional group checks, assert manually after the context exits.
When it happens
Trigger: Calling RaisesGroup(ValueError, allow_unwrapped=True, match='foo') or RaisesGroup(ValueError, allow_unwrapped=True, check=fn). Hits raises.py:984.
Common situations: Developer wants to both tolerate an unwrapped exception and assert a group-level message/check; not realizing the unwrapped path skips those checks.
Related errors
- You cannot specify multiple exceptions with `allow_unwrapped
- `allow_unwrapped=True` has no effect when expecting a `Raise
- You cannot specify a nested structure inside a RaisesGroup w
- Expected {expected}, but got {type(exc).__name__!r}. RaisesG
- absolute tolerance can't be NaN.
AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04).
Data as JSON: /data/errors/ec0fcfbec950d29a.json.
Report an issue: GitHub.