pytest-dev/pytest · error · TypeError

pytest.approx() does not support nested dictionaries: key=

Error message

pytest.approx() does not support nested dictionaries: key={!r} value={!r}
  full mapping={}

What it means

ApproxMapping.__init__ walks the expected dict and rejects any value whose type matches the expected mapping's own type (i.e. a nested dict of the same kind). pytest does this because its recursive comparison model only handles one level of mapping; nested mappings would produce ambiguous/incorrect tolerance results. The error names the offending key, value, and pretty-prints the full mapping for diagnosis.

Solutions

  1. Flatten the nested dict before comparison, or compare each sub-dict separately with its own approx() call.
  2. Restructure the expected data so numeric values live at the top level.
  3. For deeply nested numeric trees, write a recursive helper that applies approx() at each level.

Example fix

# before
assert result == approx({'a': {'b': 0.3}})
# after
assert result['a'] == approx({'b': 0.3})
Defensive patterns

Strategy: validation

Validate before calling

def is_flat_numeric_mapping(d: dict) -> bool:
    return all(not isinstance(v, dict) for v in d.values())
# usage
if is_flat_numeric_mapping(expected):
    assert actual == approx(expected)
else:
    # flatten or compare per-key
    ...

Type guard

from collections.abc import Mapping
def is_flat_mapping(obj) -> bool:
    return isinstance(obj, Mapping) and all(
        not isinstance(v, Mapping) for v in obj.values()
    )

Prevention

When it happens

Trigger: Calling approx({'outer': {'inner': 1.0}}) or approx(defaultdict(... nested defaultdict ...)). Also triggered by custom Mapping subclasses where a value is the same Mapping type. Triggered at ApproxMapping.__init__ (src/_pytest/approx.py:262-265).

Common situations: Comparing JSON-decoded nested objects, configuration trees, or sensor readings grouped by category; refactoring flat dicts into nested ones without updating the assertion.

Related errors


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

Appendix: source

Thrown at src/_pytest/approx.py:265


class ApproxMapping(Approx[Mapping[Any, Any]]):
    """Perform approximate comparisons where the expected value is a mapping
    with numeric values (the keys can be anything)."""

    def __init__(
        self,
        expected: Mapping[Any, Any],
        rel: float | Decimal | timedelta | None,
        abs: float | Decimal | timedelta | None,
        nan_ok: bool,
    ) -> None:
        __tracebackhide__ = True

        for key, value in expected.items():
            if isinstance(value, type(expected)):
                msg = "pytest.approx() does not support nested dictionaries: key={!r} value={!r}\n  full mapping={}"
                raise TypeError(msg.format(key, value, pprint.pformat(expected)))

        super().__init__(expected, rel=rel, abs=abs, nan_ok=nan_ok)

    def __repr__(self) -> str:
        return f"approx({ ({k: self._approx_scalar(v) for k, v in self.expected.items()})!r})"

    def _repr_compare(self, other_side: Mapping[object, float]) -> list[str]:
        import math

        if len(self.expected) != len(other_side):
            return [
                "Impossible to compare mappings with different sizes.",
                f"Lengths: {len(self.expected)} and {len(other_side)}",
            ]

        if self.expected.keys() != other_side.keys():
            return [
                "comparison failed.",

View on GitHub (pinned to 0d6fbdeffa)