python-poetry/poetry · error · ValueError
Unsupported file type: {file}
Error message
Unsupported file type: {file} What it means
Raised by Uploader._get_metadata() as a defensive fallback when the file is neither a .whl nor a .tar.gz. In normal flow _get_type() (error 73) rejects unknown formats first, so reaching _get_metadata with an unsupported suffix indicates the two code paths were called out of order or the file changed between checks.
Source
Thrown at src/poetry/publishing/uploader.py:366
and parts[0].endswith(".dist-info")
):
with z.open(name) as mf:
return parse_email(mf.read().decode("utf-8"))[0]
raise FileNotFoundError("METADATA not found in wheel")
elif file.suffixes[-2:] == [".tar", ".gz"]:
with tarfile.open(file, "r:gz") as tar:
for member in tar.getmembers():
parts = Path(member.name).parts
if (
len(parts) == 2
and parts[1] == "PKG-INFO"
and (pf := tar.extractfile(member))
):
return parse_email(pf.read().decode("utf-8"))[0]
raise FileNotFoundError("PKG-INFO not found in sdist")
raise ValueError(f"Unsupported file type: {file}")
def _is_file_exists_error(self, response: requests.Response) -> bool:
# based on https://github.com/pypa/twine/blob/a6dd69c79f7b5abfb79022092a5d3776a499e31b/twine/commands/upload.py#L32
status = response.status_code
reason = response.reason.lower()
text = response.text.lower()
reason_and_text = reason + text
return (
# pypiserver (https://pypi.org/project/pypiserver)
status == 409
# PyPI / TestPyPI / GCP Artifact Registry
or (status == 400 and "already exist" in reason_and_text)
# Nexus Repository OSS (https://www.sonatype.com/nexus-repository-oss)
or (status == 400 and "updating asset" in reason_and_text)
or (status == 400 and "cannot be updated" in reason_and_text)
# Artifactory (https://jfrog.com/artifactory/)
or (status == 403 and "overwrite artifact" in reason_and_text)View on GitHub (pinned to 92b74dcfe3)
Solutions
- Ensure files are validated via _get_type() (or Uploader.files filtering) before metadata extraction.
- Rebuild archives as standard .whl / .tar.gz.
- If calling Uploader internals, pre-filter to known-good formats.
- Check for concurrent processes modifying dist/ during publish.
Example fix
// before: passing a .zip straight to _get_metadata
Uploader._get_metadata(Path('pkg.zip'))
ValueError: Unsupported file type: pkg.zip
// after: only pass .whl / .tar.gz
Uploader._get_metadata(Path('pkg-1.0.0-py3-none-any.whl')) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def metadata_extractable(path: Path) -> bool:
if path.suffix == ".whl":
return True
if path.suffixes[-2:] == [".tar", ".gz"]:
return True
return False Prevention
- Always route files through Uploader's standard _get_type guard.
- Pre-filter the upload set to .whl and .tar.gz only.
- Avoid calling Uploader internals directly.
- Prevent concurrent modification of dist/ during publish.
When it happens
Trigger: _get_metadata() is invoked directly with a file whose suffix is not .whl and whose last two suffixes are not [.tar, .gz] — bypassing _get_type()'s earlier guard. Realistically an internal misuse or a race where the file was replaced between _get_type and _get_metadata.
Common situations: Internal/test code calling _get_metadata directly; a file swapped out between the type check and metadata extraction; an exotic extension that confuses suffix parsing.
Related errors
- Unknown distribution format {exts}
- Archive ({file}) does not exist
- Invalid format: {fmt}
- Unable to determine package info from path: {file_path}
- The Poetry plugin must be an instance of Plugin or Applicati
AI-assisted analysis of python-poetry/poetry@92b74dcfe3 (2026-08-04).
Data as JSON: /data/errors/615c5ae07994ca65.json.
Report an issue: GitHub.