python-poetry/poetry · error · UploadError

Redirects are not supported. Is the URL missing a trailing s

Error message

Redirects are not supported. Is the URL missing a trailing slash?

What it means

Raised by Uploader._upload_file() when the upload response is an HTTP 3xx redirect. Poetry posts with allow_redirects=False and treats any redirect as an error because PyPI's upload endpoint should be hit directly. The most common cause is a repository URL missing its trailing slash, which the server redirects.

Source

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

                if not dry_run:
                    resp = session.post(
                        url,
                        data=monitor,
                        allow_redirects=False,
                        headers={"Content-Type": monitor.content_type},
                        timeout=REQUESTS_TIMEOUT,
                    )
                if resp is None or 200 <= resp.status_code < 300:
                    bar.set_format(
                        f" - Uploading <c1>{file.name}</c1> <fg=green>%percent%%</>"
                    )
                    bar.finish()
                elif 300 <= resp.status_code < 400:
                    if self._io.output.is_decorated():
                        self._io.overwrite(
                            f" - Uploading <c1>{file.name}</c1> <error>FAILED</>"
                        )
                    raise UploadError(
                        "Redirects are not supported. "
                        "Is the URL missing a trailing slash?"
                    )
                elif resp.status_code == 400 and "was ever registered" in resp.text:
                    if not registered:
                        self._register(session, url)
                        return self._upload_file(
                            session,
                            url,
                            file,
                            dry_run,
                            skip_existing,
                            registered=True,
                        )
                    resp.raise_for_status()
                elif skip_existing and self._is_file_exists_error(resp):
                    bar.set_format(
                        f" - Uploading <c1>{file.name}</c1> <warning>File exists."

View on GitHub (pinned to 92b74dcfe3)

Solutions

  1. Add the trailing slash to the configured repository URL: `poetry config repositories.<name> https://.../legacy/`.
  2. Use the full canonical upload URL exactly as documented by the index.
  3. For http->https redirects, configure the https URL directly.
  4. Re-test with `curl -I` against the URL to confirm it does not 3xx.

Example fix

// before
$ poetry config repositories.testpypi https://test.pypi.org/legacy
$ poetry publish -r testpypi   # 3xx -> error

// after
$ poetry config repositories.testpypi https://test.pypi.org/legacy/
$ poetry publish -r testpypi
Defensive patterns

Strategy: validation

Validate before calling

def url_has_trailing_slash(url: str) -> bool:
    return url.endswith("/")

Try / catch

from poetry.publishing.uploader import UploadError

try:
    publisher.publish(...)
except UploadError as e:
    if "Redirects are not supported" in str(e):
        # append trailing slash to the configured url and retry
        ...

Prevention

When it happens

Trigger: Publishing to a repository URL like https://upload.pypi.org/legacy (no trailing slash) — the server responds 30x to the slash-appended URL, and because allow_redirects=False the 3xx is seen as an error.

Common situations: Repository configured without a trailing slash; a custom index that redirects http->https or to a canonical host; misconfigured reverse proxy that rewrites the path.

Related errors


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