pypa/pip · error · CommandError
XMLRPC request failed [code: {fault.faultCode}] {fault.fault
Error message
XMLRPC request failed [code: {fault.faultCode}]
{fault.faultString} What it means
Raised as CommandError in SearchCommand.search() at search.py:79-83 when the PyPI XMLRPC search call returns an xmlrpc.client.Fault. The fault code and fault string from the server are formatted into the message. Historically this is most common because PyPI deprecated and then disabled its XMLRPC search endpoint.
Source
Thrown at src/pip/_internal/commands/search.py:83
print_results(hits, terminal_width=terminal_width)
if pypi_hits:
return SUCCESS
return NO_MATCHES_FOUND
def search(self, query: list[str], options: Values) -> list[dict[str, str]]:
index_url = options.index
session = self.get_default_session(options)
transport = PipXmlrpcTransport(index_url, session)
pypi = xmlrpc.client.ServerProxy(index_url, transport)
try:
hits = pypi.search({"name": query, "summary": query}, "or")
except xmlrpc.client.Fault as fault:
message = (
f"XMLRPC request failed [code: {fault.faultCode}]\n{fault.faultString}"
)
raise CommandError(message)
assert isinstance(hits, list)
return hits
def transform_hits(hits: list[dict[str, str]]) -> list[TransformedHit]:
"""
The list from pypi is really a list of versions. We want a list of
packages with the list of versions stored inline. This converts the
list from pypi into one we can use.
"""
packages: dict[str, TransformedHit] = OrderedDict()
for hit in hits:
name = hit["name"]
summary = hit["summary"]
version = hit["version"]
if name not in packages.keys():
packages[name] = {View on GitHub (pinned to d7d0d0a394)
Solutions
- Stop using 'pip search' — PyPI removed the XMLRPC search endpoint; use the PyPI website or a third-party tool instead.
- Point --index at a mirror that still supports XMLRPC search, if you have one.
- Upgrade pip; modern versions warn that 'pip search' is deprecated/unavailable.
- For programmatic queries, use the PyPI JSON API (https://pypi.org/pypi/<project>/json) directly.
Example fix
# before pip search requests # XMLRPC disabled on PyPI # after — query the JSON API curl -s https://pypi.org/pypi/requests/json | jq '.info.summary'
Defensive patterns
Strategy: fallback
Validate before calling
# PyPI XMLRPC search is disabled; detect availability before relying on it
import urllib.request
try:
urllib.request.urlopen('https://pypi.org/search/?q=requests', timeout=5)
search_available = False # HTML search exists but XMLRPC does not
except Exception:
search_available = False
print('pip search via XMLRPC is unavailable; use the web/JSON API') Try / catch
import subprocess, xmlrpc.client
try:
subprocess.run(['pip','search','requests'], check=True)
except subprocess.CalledProcessError:
# fallback to the PyPI JSON API
import json, urllib.request
data = json.load(urllib.request.urlopen('https://pypi.org/pypi/requests/json'))
print(data['info']['summary']) Prevention
- Migrate off 'pip search' — PyPI permanently disabled the XMLRPC search endpoint.
- Use the PyPI JSON API (https://pypi.org/pypi/<project>/json) for programmatic lookups.
- Upgrade pip so you get the deprecation notice instead of a raw fault.
When it happens
Trigger: Running 'pip search <query>' against an index URL (default PyPI) whose XMLRPC search endpoint returns a Fault. The try/except at search.py:77-83 catches xmlrpc.client.Fault raised by pypi.search().
Common situations: PyPI permanently disabled the legacy XMLRPC search (HTTP 410 / fault); corporate mirror that does not implement search; network appliance returning an XMLRPC fault; very old pip against a changed server contract.
Related errors
- No matching distribution found for {query}
- Missing required argument (search query).
- Error reading pylock file {pylock_path_or_url!r}: {exc}
- Unexpected HTTP request on what should be a secure connectio
- --require-hashes and --no-require-hashes are mutually exclus
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/06a7d645c44f6036.json.
Report an issue: GitHub.