pytest-dev/pytest · error · ValueError

unknown capturing method: {method!r}

Error message

unknown capturing method: {method!r}

What it means

Raised by _get_multicapture (capture.py:712-723) when the requested capture method is not one of the supported literals: 'fd', 'sys', 'no', or 'tee-sys'. The method string originates from the -s/--capture CLI option or the capture_manager API, and the function explicitly enumerates every legal value before raising.

Source

Thrown at src/_pytest/capture.py:723

    def readouterr(self) -> CaptureResult[AnyStr]:
        out = self.out.snap() if self.out else ""
        err = self.err.snap() if self.err else ""
        # TODO: This type error is real, need to fix.
        return CaptureResult(out, err)  # type: ignore[arg-type]


def _get_multicapture(method: _CaptureMethod) -> MultiCapture[str]:
    if method == "fd":
        return MultiCapture(in_=FDCapture(0), out=FDCapture(1), err=FDCapture(2))
    elif method == "sys":
        return MultiCapture(in_=SysCapture(0), out=SysCapture(1), err=SysCapture(2))
    elif method == "no":
        return MultiCapture(in_=None, out=None, err=None)
    elif method == "tee-sys":
        return MultiCapture(
            in_=None, out=SysCapture(1, tee=True), err=SysCapture(2, tee=True)
        )
    raise ValueError(f"unknown capturing method: {method!r}")


# CaptureManager and CaptureFixture


class CaptureManager:
    """The capture plugin.

    Manages that the appropriate capture method is enabled/disabled during
    collection and each test phase (setup, call, teardown). After each of
    those points, the captured output is obtained and attached to the
    collection/runtest report.

    There are two levels of capture:

    * global: enabled by default and can be suppressed by the ``-s``
      option. This is always enabled/disabled during collection and each test
      phase.

View on GitHub (pinned to 98b357f69e)

Solutions

  1. Use one of the documented methods: --capture=fd (default on POSIX), --capture=sys, -s (equivalent to --capture=no), or --capture=tee-sys.
  2. Check spelling and case — the comparison is exact ('fd' not 'FD').
  3. If selecting programmatically, validate against {'fd','sys','no','tee-sys'} before passing to capture APIs.
  4. Remove any conftest/CLI injection that sets an invalid capture string.

Example fix

# before
pytest --capture=tty

# after
pytest --capture=sys
Defensive patterns

Strategy: validation

Validate before calling

VALID = {'fd', 'sys', 'no', 'tee-sys'}
def set_capture(method: str) -> str:
    assert method in VALID, f'unknown capture method {method!r}; pick from {VALID}'
    return method

Type guard

def is_valid_capture(method: str) -> bool:
    return method in {'fd', 'sys', 'no', 'tee-sys'}

Try / catch

try:
    pytest.main(['--capture', method])
except ValueError as e:
    # fall back to a known-good method
    pytest.main(['--capture', 'sys'])

Prevention

When it happens

Trigger: Invoking pytest with --capture=XXX where XXX is anything other than fd/sys/no/tee-sys; programmatic configuration that sets capture method to an arbitrary string; a typo such as --capture=FD (case-sensitive) or --capture=system.

Common situations: Misspelling the method on the command line; copying an outdated capture name from stale docs; plugins/conftest code that calls capture APIs with a custom method string that was never registered.

Related errors


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