pytest-dev/pytest · error · TypeError

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

Error message

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

What it means

Raised by RunResult._match_lines (the engine behind fnmatch_lines and re_match_lines) when the lines2 argument is not a collections.abc.Sequence. The matching algorithm requires an ordered, indexable sequence of patterns; a generator, set, or single string-in-a-non-sequence is rejected before matching begins.

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 98b357f69e)

Solutions

  1. Wrap the iterable in list() before passing: fnmatch_lines(list(patterns)).
  2. Use a list or tuple literal directly.
  3. Avoid generators/sets for line-matching arguments since order matters for consecutive matching.

Example fix

// before
result.fnmatch_lines(p for p in patterns)  # generator
// after
result.fnmatch_lines(list(patterns))
Defensive patterns

Strategy: type-guard

Validate before calling

from collections.abc import Sequence

if not isinstance(patterns, Sequence):
    patterns = list(patterns)
result.fnmatch_lines(patterns)

Type guard

from collections.abc import Sequence
from typing import Any

def is_sequence_of_str(v: Any) -> bool:
    return isinstance(v, Sequence) and all(isinstance(x, str) for x in v)

Prevention

When it happens

Trigger: Passing a generator expression, set, dict, or other non-Sequence iterable to result.fnmatch_lines(...) or result.re_match_lines(...); passing a bare non-iterable.

Common situations: Writing fnmatch_lines(x for x in patterns) with a generator instead of a list; passing a set of patterns whose ordering would be nondeterministic; refactoring from a list to another iterable type.

Related errors


AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04). Data as JSON: /data/errors/5ab1b6753d717bd8.json. Report an issue: GitHub.