pytest-dev/pytest · error · TypeError

invalid type for lines2

Error message

invalid type for lines2: {type(lines2).__name__}

What it means

Thrown by LineMatcher._match_lines() when the lines2 argument is not a collections.abc.Sequence (e.g. a generator, set, or mapping). fnmatch_lines/re_match_lines require indexable, re-iterable sequence input.

Solutions

  1. Wrap the iterable in list(): fnmatch_lines(list(...)).
  2. Pass a list or tuple literal directly.
  3. Materialize generators before the call.

Example fix

// before
result.stdout.fnmatch_lines(l.upper() for l in expected)
// after
result.stdout.fnmatch_lines([l.upper() for l in expected])
Defensive patterns

Strategy: type-guard

Validate before calling

if not isinstance(lines2, collections.abc.Sequence):
    lines2 = list(lines2)
result.stdout.fnmatch_lines(lines2)

Type guard

import collections.abc
def is_sequence_for_match(lines2: object) -> bool:
    return isinstance(lines2, collections.abc.Sequence)

Prevention

When it happens

Trigger: Passing a generator expression to fnmatch_lines: result.stdout.fnmatch_lines(l.upper() for l in lines); passing a set or dict; passing an iterator object.

Common situations: Using a generator comprehension for brevity; passing a set of expected lines; transforming lines with map() which returns an iterator in Python 3.

Related errors


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

Appendix: source

Thrown at src/_pytest/pytester.py:1703

        consecutive: bool = False,
    ) -> None:
        """Underlying implementation of ``fnmatch_lines`` and ``re_match_lines``.

        :param Sequence[str] lines2:
            List of string patterns to match. The actual format depends on
            ``match_func``.
        :param match_func:
            A callable ``match_func(line, pattern)`` where line is the
            captured line from stdout/stderr and pattern is the matching
            pattern.
        :param str match_nickname:
            The nickname for the match function that will be logged to stdout
            when a match occurs.
        :param consecutive:
            Match lines consecutively?
        """
        if not isinstance(lines2, collections.abc.Sequence):
            raise TypeError(f"invalid type for lines2: {type(lines2).__name__}")
        lines2 = self._getlines(lines2)
        lines1 = self.lines[:]
        extralines = []
        __tracebackhide__ = True
        wnick = len(match_nickname) + 1
        started = False
        for line in lines2:
            nomatchprinted = False
            while lines1:
                nextline = lines1.pop(0)
                if line == nextline:
                    self._log("exact match:", repr(line))
                    started = True
                    break
                elif match_func(nextline, line):
                    self._log(f"{match_nickname}:", repr(line))
                    self._log(
                        "{:>{width}}".format("with:", width=wnick), repr(nextline)

View on GitHub (pinned to 0d6fbdeffa)