Pre-PEP Discussion: RFC 9457 Error Responses for Package registries

Abstract

This proposal recommends that Python package registries adopt RFC 9457 (Problem Details for HTTP APIs) as a standard format for error responses in PEP 503 (Simple Repository API) and PEP 691 (JSON-based Simple API). Currently, when pip encounters HTTP errors from package registries, it displays the status code and reason phrase from the HTTP response. While HTTP/1.1 includes both fields, HTTP/2 removed the reason phrase entirely, leaving developers with only numeric status codes (e.g., “403”) and no context about why a request failed. This creates a significant user experience problem as HTTP/2 adoption accelerates. This proposal enables registries to provide structured, human-readable error information through RFC 9457’s standardized JSON format, which works consistently across both HTTP/1.1 and HTTP/2. The implementation would be optional and backwards-compatible, with clients falling back to existing behavior for non-RFC 9457 responses.

Motivation

When developers retrieve Python packages from external clients (such as UV), some registries provide error context by embedding messages in the HTTP/1.1 reason phrase field. However, HTTP/2 removed this field entirely, leaving developers with only numeric status codes under modern infrastructure. Without understanding why a package was blocked, developers must contact administrators to diagnose issues, creating unnecessary friction.

Real-World Scenario (Nexus Repository Manager):

The following is how the developer sees a custom error message when trying to download component urllib3 via pip (and using HTTP/1.1 reason phrase to display a custom message):

pip download urllib3
Looking in indexes: http://<hostName>/repository/pypi-proxy/simple
Collecting urllib3
ERROR: HTTP error 403 while getting http://<hostName>/repository/pypi-proxy/packages/urllib3/...
ERROR: Could not install requirement urllib3 because of HTTP error 403 Client Error: Requested item is quarantined ...

Technical Problems with This Approach:

  1. HTTP/2 Incompatibility: HTTP/2 removed the reason phrase field entirely (RFC 9113). Only the numeric status code is transmitted, meaning custom messages are lost when registries use HTTP/2.
  2. Not Standardized: The reason phrase format is not structured, making it impossible for clients to parse and display intelligently.
  3. Limited Length: Reason phrases have practical length limitations and cannot convey complex structured information (e.g. multiple errors, links, metadata).

With RFC 9457, this becomes:

{
  “status”: 403,
  “title”: “Package quarantined by security policy”,
  “detail”: “urllib3 version 2.6.2 has been quarantined due to security policy   violations.”
}

Ecosystem Context

RFC 9457 is already mandated in:

  • PEP 807 Index support for Trusted Publishing
  • PEP 694 Upload 2.0 API for Python Package Indexes

Rationale

Why RFC 9457?

  1. RFC 9457 is a well-established IETF standard (published July 2023) used by major APIs.
  2. Provides machine-readable + human-readable error information.
  3. Works consistently across HTTP/1.1 and HTTP/2
  4. Allows registries to add custom fields for domain-specific context

Why Optional/Recommended?

Making this recommended rather than mandatory allows:

  • Gradual adoption across diverse registry implementations.
  • No breaking changes for existing indices.
  • Progressive enhancement: clients can improve UX when RFC 9457 is detected.

Another option to support custom error messages from registries is to add a new custom header in the pip response. Similar work was done in the HuggingFace ecosystem where the header X-Error-Message is used. However, custom headers are non-standard and don’t provide structured, machine-readable error details like RFC 9457.

Specification (High-Level)

Scope: PEP 503 (Simple Repository API) and PEP 691 (JSON-based Simple API)

When Applied: HTTP error responses (4xx and 5xx status codes) from registry endpoints when pip interacts with the registry.

Minimum Required Fields:

  • status (integer): HTTP status code.
  • title (string): Short, human-readable summary.
  • detail (string): Detailed explanation of the error.

HTTP Content-Type: application/problem+json

Example Response:
{
“status”: 403,
“title”: “Package blocked by security policy”,
“detail”: “packageABC version 1.19.0 contains CVE-2021-12345 (Critical severity). Please upgrade to version 1.21.0 or later, for more details visit:``http://host.example.com``”
}

Client Behavior:

  • Clients like pip may parse and display RFC 9457 responses.
  • If Content-Type:application/problem+json is detected, clients can extract structured error details.
  • If not present, clients continue using existing error handling (fully backwards-compatible)

Related work:

What does the community think about this?. We are maintainers of a private registry and have experienced these error reporting limitations firsthand. We recognize we may not have full visibility into ecosystem-wide impacts, so we’re seeking community feedback before proposing a formal PEP.

I’m happy to collaborate with @woodruffw and others interested in moving this forward. Looking for feedback and buy-in before drafting a formal PEP.

6 Likes

Hi Luis, thank you for proposing this! I think it’s a wonderful idea. I’ve stumbled over this a number of times. I’ve moved this topic to the Packaging > Standards topic as I think this will reach the right audience here.

Should this information also be returned even if the return is 200 to maintain consistency? I think consistency in content-type between failure and success would be nice. Additionally, there are tools other than pip which interact with package indexes, so it’d be good to make this more generic to “packaging tools which interact with Simple API servers.”

I think this a valuable building block that would be good to unify across the simple API and other APIs from indexes such as uploading.

I expect folks will want to see an index implement the standard, so that they can understand how much work implementing the PEP would be.

1 Like

This seems like a great idea. +1 from me.

I’d hope that an implementation PR for PyPI would be developed as part of the PEP. I’d certainly strongly prefer that we don’t get in a situation where the PEP is approved but PyPI hasn’t yet implemented it, giving clients no motivation to add support (something which has happened in the past with other PEPs).

It would also be interesting to know how likely it is that other index providers will implement this. My gut feeling is that most simply won’t bother, at least initially. But it would be nice to be proved wrong :slightly_smiling_face:

2 Likes

Hi Emma, thank you for changing the tags to the correct topic.

My initial focus was on error responses because that’s where the immediate pain point exists (HTTP/2 eliminating reason phrases), but you raise a good point about consistency.

For success responses, package registries already return various content types (package files, JSON for metadata endpoints, etc.). Would you envision RFC 9457 applying to JSON responses specifically, or are you thinking more broadly? I want to make sure I understand the scope you’re suggesting before expanding the proposal.

@pf_moore could you please point me to the github project where this PR should be implemented?

I assume it would be PyPA/warehouse

Thinking about it more, it doesn’t really make a lot of sense to modify JSON returned by indexes (some of which is already standardized and has an expected layout) if the success information is just going to be “it worked” and duplicate the return code, so I’d say ignore me :slight_smile:

I would say that the PEP should clarify that the RFC 9457 information should only be returned in failure cases, and clients should check the status code to determine how to read the payload contents.

Not Paul, but this is the repository that backs pypi.org which Paul is talking about: GitHub - pypi/warehouse: The Python Package Index

1 Like

Thanks for opening this discussion @lgonzalez! I also want to register my hearty support for this idea; I think structured error messages on index responses would be a significant boon to the ecosystem.

I concur with Emma and Paul about the value of having this implemented within PyPI (i.e. Warehouse) from the get-go, since that’s where it’ll have the most immediate impact. The links those two shared are correct, and I’d be happy to point you at the right parts of the code within PyPI for where this would go – if I’m right, it should be a pretty local change since we’d only need to update the error handling in the index responses :slightly_smiling_face:

1 Like

IWBNI there were internal warehouse APIs that eventually 694 and 807 can just call for their own (eventual) use of RFC 9457 error responses.

2 Likes