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

  1. Ensure files are validated via _get_type() (or Uploader.files filtering) before metadata extraction.
  2. Rebuild archives as standard .whl / .tar.gz.
  3. If calling Uploader internals, pre-filter to known-good formats.
  4. 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

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


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