{"id":"c3e0a8b339f979ff","repo":"python-poetry/poetry","slug":"the-pypi-repository-cannot-be-configured-with-a-cu","errorCode":null,"errorMessage":"The PyPI repository cannot be configured with a custom url.","messagePattern":"The PyPI repository cannot be configured with a custom url\\.","errorType":"validation","errorClass":"InvalidSourceError","httpStatus":null,"severity":"error","filePath":"src/poetry/factory.py","lineNumber":223,"sourceCode":"    @classmethod\n    def create_package_source(\n        cls, source: dict[str, str], config: Config, disable_cache: bool = False\n    ) -> HTTPRepository:\n        from poetry.repositories.exceptions import InvalidSourceError\n        from poetry.repositories.legacy_repository import LegacyRepository\n        from poetry.repositories.pypi_repository import PyPiRepository\n        from poetry.repositories.single_page_repository import SinglePageRepository\n\n        try:\n            name = source[\"name\"]\n        except KeyError:\n            raise InvalidSourceError(\"Missing [name] in source.\")\n\n        pool_size = config.installer_max_workers\n\n        if name.lower() == \"pypi\":\n            if \"url\" in source:\n                raise InvalidSourceError(\n                    \"The PyPI repository cannot be configured with a custom url.\"\n                )\n            return PyPiRepository(\n                config=config,\n                disable_cache=disable_cache,\n                pool_size=pool_size,\n            )\n\n        try:\n            url = source[\"url\"]\n        except KeyError:\n            raise InvalidSourceError(f\"Missing [url] in source {name!r}.\")\n\n        repository_class = LegacyRepository\n\n        if re.match(r\".*\\.(htm|html)$\", url):\n            repository_class = SinglePageRepository\n","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/python-poetry/poetry/blob/92b74dcfe348d0e01e14d40d6c1fa47a4ee04a54/src/poetry/factory.py#L205-L241","documentation":"Raised by Factory.create_package_source when a source entry is named 'pypi' (case-insensitive) AND also provides a 'url' key. Poetry treats PyPI as a built-in repository with a fixed URL and refuses any override. The guard is at src/poetry/factory.py:221-225 and throws InvalidSourceError.","triggerScenarios":"Calling Factory.create_package_source({'name': 'pypi', 'url': '...'}) or having a [[tool.poetry.source]] table in pyproject.toml with name = \"pypi\" plus a url = \"...\" line. Any case variant like 'PyPI' triggers it because the check uses name.lower() == 'pypi'.","commonSituations":"A developer tries to point Poetry at a private mirror by reusing the name 'pypi', or migrates from pip's index-url config and copies the name verbatim. Also occurs when redirecting PyPI through a corporate proxy.","solutions":["Rename the source to something other than 'pypi' (e.g. 'my-mirror') and keep its url — custom sources are allowed a url.","If you truly want to override PyPI's URL, configure it via Poetry's repositories.pypi.url setting or environment POETRY_PYPI_URL, not a source table named 'pypi'.","Remove the url line from the 'pypi' source entry if you only wanted to disable/enable default PyPI."],"exampleFix":"# before\n[[tool.poetry.source]]\nname = \"pypi\"\nurl = \"https://pypi.org/simple\"\n\n# after (private mirror)\n[[tool.poetry.source]]\nname = \"my-mirror\"\nurl = \"https://mirrors.example.com/pypi/simple\"","handlingStrategy":"validation","validationCode":"def validate_source(source: dict) -> None:\n    name = source.get('name', '')\n    if name.lower() == 'pypi' and 'url' in source:\n        raise ValueError(\n            \"Source named 'pypi' must not set 'url'; rename the source or drop the url.\"\n        )","typeGuard":null,"tryCatchPattern":"from poetry.repositories.exceptions import InvalidSourceError\n\ntry:\n    Factory.create_package_source(source, config)\nexcept InvalidSourceError as e:\n    if 'cannot be configured with a custom url' in str(e):\n        source = {k: v for k, v in source.items() if k != 'url'} or {\n            **source, 'name': source['name'] + '-mirror'\n        }\n        Factory.create_package_source(source, config)","preventionTips":["Never name a custom source 'pypi'; reserve that name for the default index.","Lint pyproject.toml sources in CI with a schema check that rejects name='pypi' + url."],"tags":["configuration","pypi","source-repository","pyproject"],"analyzedSha":"92b74dcfe348d0e01e14d40d6c1fa47a4ee04a54","analyzedAt":"2026-08-04T20:33:34.072Z","schemaVersion":2}