{"id":"5477749bbe58c8af","repo":"python-poetry/poetry","slug":"unknown-distribution-format-exts","errorCode":null,"errorMessage":"Unknown distribution format {exts}","messagePattern":"Unknown distribution format (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/poetry/publishing/uploader.py","lineNumber":337,"sourceCode":"        data_to_send = []\n        for key, value in data.items():\n            if not isinstance(value, (list, tuple)):\n                data_to_send.append((key, value))\n            else:\n                for item in value:\n                    data_to_send.append((key, item))\n\n        return data_to_send\n\n    @staticmethod\n    def _get_type(file: Path) -> Literal[\"bdist_wheel\", \"sdist\"]:\n        exts = file.suffixes\n        if exts and exts[-1] == \".whl\":\n            return \"bdist_wheel\"\n        elif len(exts) >= 2 and \"\".join(exts[-2:]) == \".tar.gz\":\n            return \"sdist\"\n\n        raise ValueError(\"Unknown distribution format \" + \"\".join(exts))\n\n    @staticmethod\n    def _get_metadata(file: Path) -> RawMetadata:\n        if file.suffix == \".whl\":\n            with zipfile.ZipFile(file) as z:\n                for name in z.namelist():\n                    parts = Path(name).parts\n                    if (\n                        len(parts) == 2\n                        and parts[1] == \"METADATA\"\n                        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:","sourceCodeStart":319,"sourceCodeEnd":355,"githubUrl":"https://github.com/python-poetry/poetry/blob/92b74dcfe348d0e01e14d40d6c1fa47a4ee04a54/src/poetry/publishing/uploader.py#L319-L355","documentation":"Raised by Uploader._get_type() (a staticmethod) when the file's suffixes are neither a trailing .whl nor a trailing .tar.gz. _get_type classifies an archive as bdist_wheel or sdist; anything else is rejected before metadata extraction. Used to filter/gate which files can be uploaded.","triggerScenarios":"Uploader is handed a file whose extension is not .whl or .tar.gz — e.g. .zip, .tar.bz2, .egg, .exe, or a file with no recognised archive suffix. _get_type runs during upload preparation.","commonSituations":"An old .egg or .zip left in dist/; a build backend that emits non-standard formats; a glob that picked up a README or metadata file; a typo'd filename.","solutions":["Build standard formats only: `poetry build` produces .whl and .tar.gz.","Remove or exclude non-standard files from the upload set (e.g. delete stray .zip/.egg in dist/).","If you genuinely need .tar.bz2 or .zip, rebuild as wheel/sdist instead.","Inspect dist/ before publishing to confirm only .whl and .tar.gz are present."],"exampleFix":"// before: stray .zip in dist/\n$ ls dist/\nmypkg-1.0.0-py3-none-any.whl  mypkg-1.0.0.zip\nValueError: Unknown distribution format .zip\n\n// after\n$ rm dist/mypkg-1.0.0.zip\n$ poetry publish","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef is_supported_archive(path: Path) -> bool:\n    suffixes = path.suffixes\n    return (suffixes and suffixes[-1] == \".whl\") or (\n        len(suffixes) >= 2 and \"\".join(suffixes[-2:]) == \".tar.gz\"\n    )","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Build only standard formats with `poetry build`.","Clean dist/ of non-.whl/.tar.gz files before publishing.","Inspect dist/ in CI before the upload step.","Avoid mixing legacy formats (.egg/.zip) into the build output."],"tags":["publishing","archive","format","build"],"analyzedSha":"92b74dcfe348d0e01e14d40d6c1fa47a4ee04a54","analyzedAt":"2026-08-04T20:33:34.072Z","schemaVersion":2}