Skip to content
Latchkey

pypiserver twine "409 File already exists" in CI

twine got 409 because a file with that name and version already exists on the private pypiserver, which by default refuses overwrites. Re-uploading the same version is blocked; bump the version.

What this error means

twine upload fails with "HTTPError: 409 Conflict from ... file already exists" for the wheel or sdist being uploaded.

twine
Uploading internal_lib-1.0.0-py3-none-any.whl
HTTPError: 409 Conflict from https://pypi.internal.example.com/
File already exists. (Only overwrite it if you are sure.)

Common causes

The version was already uploaded

PyPI-style servers treat published files as immutable; re-uploading the same version and filename conflicts with the existing file.

CI re-ran the publish without a version bump

A retried release job rebuilds the same version, colliding with the already-uploaded artifact.

How to fix it

Bump the version and rebuild

  1. Increment the version so the filename is new.
  2. Rebuild the distribution.
  3. Upload the new version.
Terminal
# bump version in pyproject.toml, then:
python -m build
twine upload dist/*

Skip existing files for idempotent re-runs

twine can skip files that already exist so a retried job does not fail on the conflict.

Terminal
twine upload --skip-existing dist/*

How to prevent it

  • Never republish an existing version; bump instead.
  • Use --skip-existing for retry-safe publish steps.
  • Guard the release job so it only runs on new version tags.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →