pypa/pip · error · CommandError
XMLRPC request failed [code: {fault.faultCode}]\n{fault.faul
Error message
XMLRPC request failed [code: {fault.faultCode}]\n{fault.faultString} What it means
Raised by SearchCommand.search() when the XML-RPC call to the package index returns an xmlrpc.client.Fault. The fault code and fault string from the remote server are embedded in the message. Most commonly this occurs because PyPI permanently deprecated and disabled its XML-RPC search endpoint, causing every search request to fault server-side.
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 f399c37189)
Solutions
- Stop using `pip search`; PyPI no longer supports it. Search via the PyPI website (pypi.org/search) or the JSON API instead.
- If using a private/custom index, verify it implements the XML-RPC `search` method.
- Check for proxy or TLS interception that could corrupt the XML-RPC response.
- For programmatic package discovery, query https://pypi.org/simple/ or the PyPI JSON API (https://pypi.org/pypi/<name>/json).
Example fix
# before (broken on modern PyPI) pip search requests # after: use the JSON API curl -s https://pypi.org/pypi/requests/json | jq '.info.summary'
Defensive patterns
Strategy: fallback
Validate before calling
import urllib.request, json
def search_pypi_json(name: str) -> dict:
# Reliable alternative to the deprecated XML-RPC search
with urllib.request.urlopen(f'https://pypi.org/pypi/{name}/json') as r:
return json.load(r)
Try / catch
try:
subprocess.run(['pip', 'search', query], check=True)
except subprocess.CalledProcessError:
# Fallback to the JSON API since PyPI XML-RPC search is deprecated
result = search_pypi_json(query)
Prevention
- Migrate off pip search entirely; PyPI disabled the XML-RPC endpoint.
- Use https://pypi.org/pypi/<name>/json for programmatic lookups.
- Catch CalledProcessError and fall back to the JSON API.
When it happens
Trigger: Calling `pip search <query>` against pypi.org (default), or against a custom --index that does not implement the XML-RPC search method, or when a proxy/firewall returns a fault-formatted response.
Common situations: Any modern invocation of `pip search` against PyPI, since PyPI removed XML-RPC search support; using a private index that lacks the search method; intermittent network/proxy issues that corrupt the XML-RPC payload.
Related errors
- Missing required argument (search query).
- Could not install requirement {req} because of HTTP error {e
- Packages installed from PyPI cannot depend on packages which
- No matching distribution found for {query}
- Can not perform a '--user' install. User site-packages are d
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/43a5a3ae6af2c66f.
Report an issue: GitHub.