pytest-dev/pytest · error · ValueError

number is negative

Error message

number is negative

What it means

This is the inner ValueError raised when the line-number field of a warning filter specification is a valid integer but negative. The 'number is negative' string is embedded into the lineno error template (error 63) that is actually shown to the user. Line numbers in warning filters must be non-negative.

Source

Thrown at src/_pytest/config/__init__.py:2309

    except warnings._OptionError as e:
        raise UsageError(error_template.format(error=str(e))) from None
    try:
        category: type[Warning] = _resolve_warning_category(category_)
    except ImportError:
        raise
    except Exception:
        exc_info = ExceptionInfo.from_current()
        exception_text = exc_info.getrepr(style="native")
        raise UsageError(error_template.format(error=exception_text)) from None
    if message and escape:
        message = re.escape(message)
    if module and escape:
        module = re.escape(module) + r"\Z"
    if lineno_:
        try:
            lineno = int(lineno_)
            if lineno < 0:
                raise ValueError("number is negative")
        except ValueError as e:
            raise UsageError(
                error_template.format(error=f"invalid lineno {lineno_!r}: {e}")
            ) from None
    else:
        lineno = 0
    try:
        re.compile(message)
        re.compile(module)
    except re.error as e:
        raise UsageError(
            error_template.format(error=f"Invalid regex {e.pattern!r}: {e}")
        ) from None
    return action, message, category, module, lineno


def _resolve_warning_category(category: str) -> type[Warning]:
    """

View on GitHub (pinned to 98b357f69e)

Solutions

  1. Use 0 (or omit the field) to mean 'any line number'.
  2. Use a specific positive line number to target a particular source line.
  3. Re-check field order: action:message:category:module:lineno — the 5th field is lineno.

Example fix

# before
[pytest]
filterwarnings = ["ignore::DeprecationWarning::mymod:-1"]

# after
[pytest]
filterwarnings = ["ignore::DeprecationWarning::mymod:0"]
Defensive patterns

Strategy: validation

Validate before calling

def validate_lineno_field(spec: str) -> int:
    parts = spec.split(':')
    if len(parts) >= 5 and parts[4].strip():
        lineno = int(parts[4].strip())
        if lineno < 0:
            raise ValueError(f'lineno must be >= 0, got {lineno}')
        return lineno
    return 0

Type guard

def is_valid_lineno(value: str) -> bool:
    try:
        return int(value) >= 0
    except ValueError:
        return False

Prevention

When it happens

Trigger: A filter string with a 5th field that parses as int but is < 0, e.g. 'ignore::DeprecationWarning:::module:-1' or -W 'ignore::DeprecationWarning:::mymod:-5'. The code does int(lineno_) then checks lineno < 0 and raises ValueError('number is negative').

Common situations: Off-by-one or sign mistakes when hand-crafting a lineno-scoped filter; accidentally passing a negative value from a templated/scripted filterwarnings generation; misreading the filter field order and putting a value meant elsewhere into the lineno slot.

Related errors


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