{"id":"d05cf93a3037bac2","repo":"python-poetry/poetry","slug":"archive-file-does-not-exist","errorCode":null,"errorMessage":"Archive ({file}) does not exist","messagePattern":"Archive \\((.+?)\\) does not exist","errorType":"exception","errorClass":"UploadError","httpStatus":null,"severity":"error","filePath":"src/poetry/publishing/uploader.py","lineNumber":213,"sourceCode":"        skip_existing: bool = False,\n    ) -> None:\n        for file in self.files:\n            self._upload_file(session, url, file, dry_run, skip_existing)\n\n    def _upload_file(\n        self,\n        session: requests.Session,\n        url: str,\n        file: Path,\n        dry_run: bool = False,\n        skip_existing: bool = False,\n        *,\n        registered: bool = False,\n    ) -> None:\n        from cleo.ui.progress_bar import ProgressBar\n\n        if not file.is_file():\n            raise UploadError(f\"Archive ({file}) does not exist\")\n\n        data = self.post_data(file)\n        data.update({\":action\": \"file_upload\", \"protocol_version\": \"1\"})\n\n        data_to_send: list[tuple[str, Any]] = self._prepare_data(data)\n\n        with file.open(\"rb\") as fp:\n            data_to_send.append(\n                (\"content\", (file.name, fp, \"application/octet-stream\"))\n            )\n            encoder = MultipartEncoder(data_to_send)\n            bar = ProgressBar(self._io, max=encoder.len)\n            bar.set_format(f\" - Uploading <c1>{file.name}</c1> <b>%percent%%</b>\")\n            monitor = MultipartEncoderMonitor(\n                encoder, lambda monitor: bar.set_progress(monitor.bytes_read)\n            )\n\n            bar.start()","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/python-poetry/poetry/blob/92b74dcfe348d0e01e14d40d6c1fa47a4ee04a54/src/poetry/publishing/uploader.py#L195-L231","documentation":"Raised by Uploader._upload_file() when the given Path fails file.is_file() — i.e. the archive to upload does not exist or is not a regular file. This is a precondition check before reading the file contents for the multipart upload.","triggerScenarios":"Calling publish/upload with a files list pointing at a non-existent or non-file path — e.g. dist/ was never built, the glob matched nothing, or the path is a directory.","commonSituations":"Running `poetry publish` before `poetry build`; building to a non-default dist dir; a stale file list after `dist/` was cleaned; path case/spacing mismatch on case-sensitive filesystems.","solutions":["Run `poetry build` first to produce the .whl / .tar.gz in dist/.","Verify the files list the Uploader was given — ensure the paths exist with `ls dist/`.","If using a custom dist dir, pass it correctly so the Uploader looks in the right place.","Re-run build if dist/ was cleaned or never created."],"exampleFix":"// before\n$ poetry publish   # dist/ empty or missing\nUploadError: Archive (dist/mypkg-1.0.0-py3-none-any.whl) does not exist\n\n// after\n$ poetry build\n$ poetry publish","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef archives_exist(paths: list[Path]) -> bool:\n    return all(p.is_file() for p in paths)","typeGuard":null,"tryCatchPattern":"from poetry.publishing.uploader import UploadError\n\ntry:\n    publisher.publish(...)\nexcept UploadError as e:\n    if \"does not exist\" in str(e):\n        # build first, then retry\n        ...","preventionTips":["Always run `poetry build` before `poetry publish`.","Script the release flow as build-then-publish.","Verify dist/ contents in CI before the publish step.","Avoid manual file list manipulation in the Uploader."],"tags":["publishing","file","archive","build"],"analyzedSha":"92b74dcfe348d0e01e14d40d6c1fa47a4ee04a54","analyzedAt":"2026-08-04T20:33:34.072Z","schemaVersion":2}