{"id":"615c5ae07994ca65","repo":"python-poetry/poetry","slug":"unsupported-file-type-file","errorCode":null,"errorMessage":"Unsupported file type: {file}","messagePattern":"Unsupported file type: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/poetry/publishing/uploader.py","lineNumber":366,"sourceCode":"                        and parts[0].endswith(\".dist-info\")\n                    ):\n                        with z.open(name) as mf:\n                            return parse_email(mf.read().decode(\"utf-8\"))[0]\n            raise FileNotFoundError(\"METADATA not found in wheel\")\n\n        elif file.suffixes[-2:] == [\".tar\", \".gz\"]:\n            with tarfile.open(file, \"r:gz\") as tar:\n                for member in tar.getmembers():\n                    parts = Path(member.name).parts\n                    if (\n                        len(parts) == 2\n                        and parts[1] == \"PKG-INFO\"\n                        and (pf := tar.extractfile(member))\n                    ):\n                        return parse_email(pf.read().decode(\"utf-8\"))[0]\n            raise FileNotFoundError(\"PKG-INFO not found in sdist\")\n\n        raise ValueError(f\"Unsupported file type: {file}\")\n\n    def _is_file_exists_error(self, response: requests.Response) -> bool:\n        # based on https://github.com/pypa/twine/blob/a6dd69c79f7b5abfb79022092a5d3776a499e31b/twine/commands/upload.py#L32\n        status = response.status_code\n        reason = response.reason.lower()\n        text = response.text.lower()\n        reason_and_text = reason + text\n\n        return (\n            # pypiserver (https://pypi.org/project/pypiserver)\n            status == 409\n            # PyPI / TestPyPI / GCP Artifact Registry\n            or (status == 400 and \"already exist\" in reason_and_text)\n            # Nexus Repository OSS (https://www.sonatype.com/nexus-repository-oss)\n            or (status == 400 and \"updating asset\" in reason_and_text)\n            or (status == 400 and \"cannot be updated\" in reason_and_text)\n            # Artifactory (https://jfrog.com/artifactory/)\n            or (status == 403 and \"overwrite artifact\" in reason_and_text)","sourceCodeStart":348,"sourceCodeEnd":384,"githubUrl":"https://github.com/python-poetry/poetry/blob/92b74dcfe348d0e01e14d40d6c1fa47a4ee04a54/src/poetry/publishing/uploader.py#L348-L384","documentation":"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.","triggerScenarios":"_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.","commonSituations":"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.","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."],"exampleFix":"// before: passing a .zip straight to _get_metadata\nUploader._get_metadata(Path('pkg.zip'))\nValueError: Unsupported file type: pkg.zip\n\n// after: only pass .whl / .tar.gz\nUploader._get_metadata(Path('pkg-1.0.0-py3-none-any.whl'))","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef metadata_extractable(path: Path) -> bool:\n    if path.suffix == \".whl\":\n        return True\n    if path.suffixes[-2:] == [\".tar\", \".gz\"]:\n        return True\n    return False","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["publishing","archive","format","internal-api"],"analyzedSha":"92b74dcfe348d0e01e14d40d6c1fa47a4ee04a54","analyzedAt":"2026-08-04T20:33:34.072Z","schemaVersion":2}