pytest-dev/pytest · error · AssertionError
not found in warning list
Error message
{cls!r} not found in warning list What it means
Raised by WarningsRecorder.pop when no recorded warning matches the requested category cls. pop searches for an exact category match first, then the most-derived subclass match; if neither is found it raises AssertionError. This signals a test expectation failure: the user asked for a warning of that category that was never emitted.
Solutions
- Check membership before popping: if any(w.category is cls for w in recorder): recorder.pop(cls).
- Use pytest.warns(ExpectedCategory) at the assertion level rather than manual pop, so pytest reports DID NOT WARN with context.
- Inspect recorder.list to see what was actually emitted and correct the expected category.
Example fix
// before
warn = recorder.pop(DeprecationWarning) # AssertionError if absent
// after
matches = [w for w in recorder if issubclass(w.category, DeprecationWarning)]
assert matches, f'no DeprecationWarning; got {[w.category.__name__ for w in recorder]}'
warn = matches[0] Defensive patterns
Strategy: try-catch
Validate before calling
matches = [w for w in recorder if issubclass(w.category, cls)]
assert matches, f'{cls!r} not in {[w.category.__name__ for w in recorder]}'
warn = matches[0] Type guard
def recorder_has_category(recorder, cls) -> bool:
return any(issubclass(w.category, cls) for w in recorder) Try / catch
try:
warn = recorder.pop(cls)
except AssertionError:
# handle missing-warning expectation explicitly
raise AssertionError(f'expected {cls}; got {[w.category.__name__ for w in recorder]}') Prevention
- Check recorder membership before pop.
- Prefer pytest.warns(ExpectedCategory) at the assertion boundary over manual pop.
- Inspect recorder.list to confirm categories before popping.
When it happens
Trigger: Calling recorder.pop(UserWarning) or pop(DeprecationWarning) when the recorded list contains no warning of that category. Reached when best_idx stays None after the loop.
Common situations: Inspecting a WarningsRecorder/pytest.warns result and popping a category the code under test did not emit; ordering bugs where pop is called twice for the same warning; mismatched category assumptions after a refactor.
Related errors
- Cannot enter twice
- Cannot exit without entering first
- approx() is not supported in a boolean context. Did you…
- exceptions must be derived from Warning, not
- object (type: ) must be callable
AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11).
Data as JSON: /api/errors/b90cdefc6a9095d8.
Report an issue: GitHub.
Appendix: source
Thrown at src/_pytest/recwarn.py:228
def pop(self, cls: type[Warning] = Warning) -> warnings.WarningMessage:
"""Pop the first recorded warning which is an instance of ``cls``,
but not an instance of a child class of any other match.
Raises ``AssertionError`` if there is no match.
"""
best_idx: int | None = None
for i, w in enumerate(self._list):
if w.category == cls:
return self._list.pop(i) # exact match, stop looking
if issubclass(w.category, cls) and (
best_idx is None
or not issubclass(w.category, self._list[best_idx].category)
):
best_idx = i
if best_idx is not None:
return self._list.pop(best_idx)
__tracebackhide__ = True
raise AssertionError(f"{cls!r} not found in warning list")
def clear(self) -> None:
"""Clear the list of recorded warnings."""
self._list[:] = []
# Type ignored because we basically want the `catch_warnings` generic type
# parameter to be ourselves but that is not possible(?).
def __enter__(self) -> Self: # type: ignore[override]
if self._entered:
__tracebackhide__ = True
raise RuntimeError(f"Cannot enter {self!r} twice")
_list = super().__enter__()
# record=True means it's None.
assert _list is not None
self._list = _list
warnings.simplefilter("always")
return self
View on GitHub (pinned to 0d6fbdeffa)