python-poetry/poetry · error · UploadError

Archive ({file}) does not exist

Error message

Archive ({file}) does not exist

What it means

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.

Source

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

        skip_existing: bool = False,
    ) -> None:
        for file in self.files:
            self._upload_file(session, url, file, dry_run, skip_existing)

    def _upload_file(
        self,
        session: requests.Session,
        url: str,
        file: Path,
        dry_run: bool = False,
        skip_existing: bool = False,
        *,
        registered: bool = False,
    ) -> None:
        from cleo.ui.progress_bar import ProgressBar

        if not file.is_file():
            raise UploadError(f"Archive ({file}) does not exist")

        data = self.post_data(file)
        data.update({":action": "file_upload", "protocol_version": "1"})

        data_to_send: list[tuple[str, Any]] = self._prepare_data(data)

        with file.open("rb") as fp:
            data_to_send.append(
                ("content", (file.name, fp, "application/octet-stream"))
            )
            encoder = MultipartEncoder(data_to_send)
            bar = ProgressBar(self._io, max=encoder.len)
            bar.set_format(f" - Uploading <c1>{file.name}</c1> <b>%percent%%</b>")
            monitor = MultipartEncoderMonitor(
                encoder, lambda monitor: bar.set_progress(monitor.bytes_read)
            )

            bar.start()

View on GitHub (pinned to 92b74dcfe3)

Solutions

  1. Run `poetry build` first to produce the .whl / .tar.gz in dist/.
  2. Verify the files list the Uploader was given — ensure the paths exist with `ls dist/`.
  3. If using a custom dist dir, pass it correctly so the Uploader looks in the right place.
  4. Re-run build if dist/ was cleaned or never created.

Example fix

// before
$ poetry publish   # dist/ empty or missing
UploadError: Archive (dist/mypkg-1.0.0-py3-none-any.whl) does not exist

// after
$ poetry build
$ poetry publish
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def archives_exist(paths: list[Path]) -> bool:
    return all(p.is_file() for p in paths)

Try / catch

from poetry.publishing.uploader import UploadError

try:
    publisher.publish(...)
except UploadError as e:
    if "does not exist" in str(e):
        # build first, then retry
        ...

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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