pypa/pip · error · InstallationError

Invalid requirement: {name.strip()!r}: {exc}

Error message

Invalid requirement: {name.strip()!r}: {exc}

What it means

Raised by parse_req_from_line() when the environment marker portion of a requirement line (after `;`) fails to parse as a valid PEP 508 marker. The marker string is parsed with Marker() at constructors.py:347; an InvalidMarker exception is caught and re-raised as an InstallationError showing the requirement name and the underlying parse error.

Source

Thrown at src/pip/_internal/req/constructors.py:349

    )
    return path_to_url(path)


def parse_req_from_line(name: str, line_source: str | None) -> RequirementParts:
    if is_url(name):
        marker_sep = "; "
    else:
        marker_sep = ";"
    if marker_sep in name:
        name, markers_as_string = name.split(marker_sep, 1)
        markers_as_string = markers_as_string.strip()
        if not markers_as_string:
            markers = None
        else:
            try:
                markers = Marker(markers_as_string)
            except InvalidMarker as exc:
                raise InstallationError(f"Invalid requirement: {name.strip()!r}: {exc}")
    else:
        markers = None
    name = name.strip()
    req_as_string = None
    path = os.path.normpath(os.path.abspath(name))
    link = None

    if is_url(name):
        link = Link(name)
        extras: set[str] = set()
    else:
        p, extras = strip_extras(path)
        url = _get_url_from_path(p, name)
        if url is not None:
            link = Link(url)

    # it's a local file, dir, or url
    if link:

View on GitHub (pinned to d7d0d0a394)

Solutions

  1. Read the marker error in the message and correct the operator — markers use `==`, `!=`, `<`, `<=`, `>`, `>=`, `in`, `not in`.
  2. Ensure marker variable names are valid PEP 508 environment markers (python_version, sys_platform, platform_machine, etc.).
  3. Quote string literals with single or double quotes consistently.
  4. Test the marker in isolation: `python -c "from packaging.markers import Marker; Marker('python_version == \"3.10\"')"`.

Example fix

# before
package ; python_version = "3.10"
# after
package ; python_version == "3.10"
Defensive patterns

Strategy: validation

Validate before calling

from packaging.markers import Marker, InvalidMarker

def validate_marker(marker_str: str) -> Marker:
    try:
        return Marker(marker_str)
    except InvalidMarker as e:
        raise ValueError(f"Invalid marker {marker_str!r}: {e}") from e

# split requirement on ';' and validate the marker half before pip

Type guard

from packaging.markers import Marker, InvalidMarker

def is_valid_marker(s: str) -> bool:
    try:
        Marker(s)
        return True
    except InvalidMarker:
        return False

Try / catch

null

Prevention

When it happens

Trigger: A requirement line like `package ; python_version = "3.10"` (using `=` instead of `==` inside the marker), `package ; os_name is "posix"` with invalid token, or any malformed marker expression. The split happens on `;` (or `; ` for URLs).

Common situations: Typos in marker operators (= vs ==). Unsupported marker fields. Mismatched quotes. Copy-pasting markers from sources that mangled quote characters.

Related errors


AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04). Data as JSON: /data/errors/530bddd32a9b0b5c.json. Report an issue: GitHub.