python-poetry/poetry · error · ValueError
The name [pypi] is reserved for repositories
Error message
The name [pypi] is reserved for repositories
What it means
LegacyRepository.__init__ rejects the repository name 'pypi' because it collides with the built-in PyPIRepository that Poetry registers under that exact name (legacy_repository.py:38-39). Using it would shadow the default PyPI source and break resolution, so construction fails fast.
Source
Thrown at src/poetry/repositories/legacy_repository.py:39
from packaging.utils import NormalizedName
from poetry.core.constraints.version import Version
from poetry.core.packages.utils.link import Link
from poetry.config.config import Config
class LegacyRepository(HTTPRepository):
def __init__(
self,
name: str,
url: str,
*,
config: Config | None = None,
disable_cache: bool = False,
pool_size: int = requests.adapters.DEFAULT_POOLSIZE,
) -> None:
if name == "pypi":
raise ValueError("The name [pypi] is reserved for repositories")
super().__init__(
name,
url.rstrip("/"),
config=config,
disable_cache=disable_cache,
pool_size=pool_size,
)
def package(self, name: str, version: Version) -> Package:
"""
Retrieve the release information.
This is a heavy task which takes time.
We have to download a package to get the dependencies.
We also need to download every file matching this release
to get the various hashes.
View on GitHub (pinned to 92b74dcfe3)
Solutions
- Choose a distinct source name, e.g. `poetry source add my-pypi <url>`.
- If you genuinely want to override the default PyPI URL, configure the PyPI repository's URL instead of adding a new 'pypi' source.
- Rename the existing offending entry in pyproject.toml [[tool.poetry.source]] to a non-reserved name.
Example fix
// before [[tool.poetry.source]] name = "pypi" url = "https://mymirror.example.com/simple/" // after [[tool.poetry.source]] name = "mymirror" url = "https://mymirror.example.com/simple/"
Defensive patterns
Strategy: validation
Validate before calling
RESERVED = {"pypi"}
if source_name.lower() in RESERVED:
raise ValueError(f"'{source_name}' is reserved; choose another source name")
repo = LegacyRepository(name=source_name, url=url) Try / catch
try:
repo = LegacyRepository(name=name, url=url)
except ValueError as e:
if "reserved" in str(e):
name = f"{name}-custom"
repo = LegacyRepository(name=name, url=url)
raise Prevention
- Never name a custom source 'pypi'.
- Use descriptive, unique source names.
- Validate source names in config-loading code before constructing repositories.
When it happens
Trigger: Instantiating LegacyRepository(name="pypi", url=...) directly, or running `poetry source add pypi <url>` which constructs a LegacyRepository with that name.
Common situations: A user adding a custom/legacy source and carelessly naming it 'pypi'; copy-pasting a source config that reused the reserved name.
Related errors
- Setting {self.argument('key')} does not exist
- You can only pass one value.
- "{value}" is an invalid value for {key}
- Repository {repository_name} is not defined
- FileCache.hash_type is unknown value: '{self.hash_type}'.
AI-assisted analysis of python-poetry/poetry@92b74dcfe3 (2026-08-04).
Data as JSON: /data/errors/4087aa46035d2581.json.
Report an issue: GitHub.