python-poetry/poetry · error · UploadError

HTTP Error {e.response.status_code}: {e.response.reason} | {

Error message

HTTP Error {e.response.status_code}: {e.response.reason} | {e.response.content!r}

What it means

Raised by Uploader._upload_file() inside the requests.RequestException handler when the exception carries a response (e.g. HTTPError from raise_for_status). It wraps status code, reason phrase, and raw response body into an UploadError so the caller sees a single error type with diagnostic detail.

Source

Thrown at src/poetry/publishing/uploader.py:290

                        f" - Uploading <c1>{file.name}</c1> <warning>File exists."
                        " Skipping</>"
                    )
                    bar.display()
                else:
                    resp.raise_for_status()

            except requests.RequestException as e:
                if self._io.output.is_decorated():
                    self._io.overwrite(
                        f" - Uploading <c1>{file.name}</c1> <error>FAILED</>"
                    )

                if e.response is not None:
                    message = (
                        f"HTTP Error {e.response.status_code}: "
                        f"{e.response.reason} | {e.response.content!r}"
                    )
                    raise UploadError(message) from e

                raise UploadError("Error connecting to repository") from e

            finally:
                self._io.write_line("")

    def _register(self, session: requests.Session, url: str) -> requests.Response:
        """
        Register a package to a repository.
        """
        data = self.post_data(self.files[0])
        data.update({":action": "submit", "protocol_version": "1"})

        data_to_send = self._prepare_data(data)
        encoder = MultipartEncoder(data_to_send)
        resp = session.post(
            url,
            data=encoder,

View on GitHub (pinned to 92b74dcfe3)

Solutions

  1. Read the embedded status code and response body — they identify the server-side problem.
  2. 401/403: verify credentials/token (`poetry config http-basic.<name>` or set the API token correctly).
  3. 4xx with a message about file size/name: fix the package metadata or reduce size.
  4. 5xx/429: retry after a short delay; check the index's status page.
  5. Confirm the upload URL is correct and the package name is registered on the index.

Example fix

// before: 403 due to invalid token
UploadError: HTTP Error 403: Forbidden | b'Invalid or non-existent authentication...'

// after
$ poetry config pypi-token.pypi pypi-xxxxxxxxxxxx
$ poetry publish
Defensive patterns

Strategy: try-catch

Try / catch

from poetry.publishing.uploader import UploadError

try:
    publisher.publish(...)
except UploadError as e:
    msg = str(e)
    if msg.startswith("HTTP Error"):
        status = int(msg.split()[2].rstrip(":"))
        # branch on status: 401/403 -> creds, 429 -> retry, 5xx -> retry
        ...

Prevention

When it happens

Trigger: The repository server returns a non-success status that is not a handled case (redirect, file-exists, ever-registered). resp.raise_for_status() raises HTTPError which is caught as RequestException with .response set; the handler re-throws UploadError with the formatted message.

Common situations: 403 Forbidden (bad token/credentials), 404 (wrong upload URL), 413 (file too large), 500/502/503 (server error), 400 with an unrelated error body, rate limiting (429).

Related errors


AI-assisted analysis of python-poetry/poetry@92b74dcfe3 (2026-08-04). Data as JSON: /data/errors/5ac5d67bc3f0a033.json. Report an issue: GitHub.