pytest-dev/pytest · error · TypeError

pytest.approx() does not support nested data structures

Error message

pytest.approx() does not support nested data structures: {!r} at index {}
  full sequence: {}

What it means

ApproxSequenceLike.__init__ rejects any element whose type matches the expected sequence's own type (e.g. a list inside a list, a tuple inside a tuple). pytest's sequence approximation is intentionally single-level: it zips expected and actual element-by-element. Nested sequences would be ambiguous about how to apply tolerance, so they are rejected up front with the offending element, its index, and the full sequence pretty-printed.

Solutions

  1. Use a numpy array and approx(np.array(...)) for multi-dimensional numeric data.
  2. Compare each inner sequence separately: `for e, a in zip(expected, actual): assert a == approx(e)`.
  3. Convert the outer container so inner and outer are different sequence types (e.g. tuple of lists).

Example fix

# before
assert actual == approx([[1.0, 2.0], [3.0, 4.0]])
# after
import numpy as np
assert np.array(actual) == approx(np.array([[1.0, 2.0], [3.0, 4.0]]))
Defensive patterns

Strategy: validation

Validate before calling

from collections.abc import Sequence
def is_flat_sequence(seq) -> bool:
    seq_t = type(seq)
    return all(not isinstance(x, seq_t) for x in seq)
# usage
if is_flat_sequence(expected):
    assert actual == approx(expected)
else:
    import numpy as np
    assert np.array(actual) == approx(np.array(expected))

Type guard

from collections.abc import Sequence
def is_flat_numeric_sequence(obj) -> bool:
    return (
        isinstance(obj, Sequence)
        and not isinstance(obj, (str, bytes))
        and all(not isinstance(x, type(obj)) for x in obj)
    )

Prevention

When it happens

Trigger: Calling approx([[1.0, 2.0], [3.0, 4.0]]), approx([(1.0, 2.0)]) where the element is the same sequence type, or approx on a custom Sequence subclass whose items are also that subclass. Triggered at ApproxSequenceLike.__init__ (src/_pytest/approx.py:360-363). Note: lists inside tuples or tuples inside lists are allowed because only same-type nesting is checked.

Common situations: Matrix/multi-dimensional data represented as nested lists; comparing batched numerical results; converting numpy arrays to nested lists for comparison.

Related errors


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

Appendix: source

Thrown at src/_pytest/approx.py:363

            yield actual[k], self.expected[k]


class ApproxSequenceLike(Approx[Sequence[Any]]):
    """Perform approximate comparisons where the expected value is a sequence of numbers."""

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

        for index, x in enumerate(expected):
            if isinstance(x, type(expected)):
                msg = "pytest.approx() does not support nested data structures: {!r} at index {}\n  full sequence: {}"
                raise TypeError(msg.format(x, index, pprint.pformat(expected)))

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

    def __repr__(self) -> str:
        seq_type = type(self.expected)
        if seq_type not in (tuple, list):
            seq_type = list
        return f"approx({seq_type(self._approx_scalar(x) for x in self.expected)!r})"

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

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

View on GitHub (pinned to 0d6fbdeffa)