{"id":"03944a2e3789c829","repo":"python-poetry/poetry","slug":"redirects-are-not-supported-is-the-url-missing-a","errorCode":null,"errorMessage":"Redirects are not supported. Is the URL missing a trailing slash?","messagePattern":"Redirects are not supported\\. Is the URL missing a trailing slash\\?","errorType":"http","errorClass":"UploadError","httpStatus":null,"severity":"error","filePath":"src/poetry/publishing/uploader.py","lineNumber":254,"sourceCode":"                if not dry_run:\n                    resp = session.post(\n                        url,\n                        data=monitor,\n                        allow_redirects=False,\n                        headers={\"Content-Type\": monitor.content_type},\n                        timeout=REQUESTS_TIMEOUT,\n                    )\n                if resp is None or 200 <= resp.status_code < 300:\n                    bar.set_format(\n                        f\" - Uploading <c1>{file.name}</c1> <fg=green>%percent%%</>\"\n                    )\n                    bar.finish()\n                elif 300 <= resp.status_code < 400:\n                    if self._io.output.is_decorated():\n                        self._io.overwrite(\n                            f\" - Uploading <c1>{file.name}</c1> <error>FAILED</>\"\n                        )\n                    raise UploadError(\n                        \"Redirects are not supported. \"\n                        \"Is the URL missing a trailing slash?\"\n                    )\n                elif resp.status_code == 400 and \"was ever registered\" in resp.text:\n                    if not registered:\n                        self._register(session, url)\n                        return self._upload_file(\n                            session,\n                            url,\n                            file,\n                            dry_run,\n                            skip_existing,\n                            registered=True,\n                        )\n                    resp.raise_for_status()\n                elif skip_existing and self._is_file_exists_error(resp):\n                    bar.set_format(\n                        f\" - Uploading <c1>{file.name}</c1> <warning>File exists.\"","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/python-poetry/poetry/blob/92b74dcfe348d0e01e14d40d6c1fa47a4ee04a54/src/poetry/publishing/uploader.py#L236-L272","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add the trailing slash to the configured repository URL: `poetry config repositories.<name> https://.../legacy/`.","Use the full canonical upload URL exactly as documented by the index.","For http->https redirects, configure the https URL directly.","Re-test with `curl -I` against the URL to confirm it does not 3xx."],"exampleFix":"// before\n$ poetry config repositories.testpypi https://test.pypi.org/legacy\n$ poetry publish -r testpypi   # 3xx -> error\n\n// after\n$ poetry config repositories.testpypi https://test.pypi.org/legacy/\n$ poetry publish -r testpypi","handlingStrategy":"validation","validationCode":"def url_has_trailing_slash(url: str) -> bool:\n    return url.endswith(\"/\")","typeGuard":null,"tryCatchPattern":"from poetry.publishing.uploader import UploadError\n\ntry:\n    publisher.publish(...)\nexcept UploadError as e:\n    if \"Redirects are not supported\" in str(e):\n        # append trailing slash to the configured url and retry\n        ...","preventionTips":["Always configure repository URLs with a trailing slash.","Copy the exact upload URL from the index documentation.","Test the URL with curl -I to ensure no redirect.","Document the canonical URL in the project's publish guide."],"tags":["publishing","network","url","redirect"],"analyzedSha":"92b74dcfe348d0e01e14d40d6c1fa47a4ee04a54","analyzedAt":"2026-08-04T20:33:34.072Z","schemaVersion":2}