python-poetry/poetry · error · InvalidSourceError

Missing [url] in source {name!r}.

Error message

Missing [url] in source {name!r}.

What it means

Raised by Factory.create_package_source when a non-PyPI source dict has a name but is missing the 'url' key. Custom (legacy) repositories must declare where they live. Thrown at src/poetry/factory.py:232-235 as InvalidSourceError, formatting the offending source name into the message.

Source

Thrown at src/poetry/factory.py:235

            raise InvalidSourceError("Missing [name] in source.")

        pool_size = config.installer_max_workers

        if name.lower() == "pypi":
            if "url" in source:
                raise InvalidSourceError(
                    "The PyPI repository cannot be configured with a custom url."
                )
            return PyPiRepository(
                config=config,
                disable_cache=disable_cache,
                pool_size=pool_size,
            )

        try:
            url = source["url"]
        except KeyError:
            raise InvalidSourceError(f"Missing [url] in source {name!r}.")

        repository_class = LegacyRepository

        if re.match(r".*\.(htm|html)$", url):
            repository_class = SinglePageRepository

        return repository_class(
            name,
            url,
            config=config,
            disable_cache=disable_cache,
            pool_size=pool_size,
        )

    @classmethod
    def create_legacy_pyproject_from_package(cls, package: Package) -> TOMLDocument:
        import tomlkit

View on GitHub (pinned to 92b74dcfe3)

Solutions

  1. Add url = "https://..." to the [[tool.poetry.source]] table named in the message.
  2. Verify with: poetry source show — it lists parsed sources and reveals the missing url.
  3. Check for typos in the key name (TOML is case-sensitive: it must be lowercase 'url').

Example fix

# before
[[tool.poetry.source]]
name = "private"

# after
[[tool.poetry.source]]
name = "private"
url = "https://repo.example.com/simple"
Defensive patterns

Strategy: validation

Validate before calling

def validate_source(source: dict) -> None:
    name = source.get('name')
    if not name:
        raise ValueError('Missing [name] in source.')
    if name.lower() != 'pypi' and 'url' not in source:
        raise ValueError(f"Missing [url] in source {name!r}.")

Try / catch

from poetry.repositories.exceptions import InvalidSourceError

try:
    Factory.create_package_source(source, config)
except InvalidSourceError as e:
    if 'Missing [url]' in str(e):
        raise SystemExit(f'Configuration error: {e}. Add a url to the source.')

Prevention

When it happens

Trigger: A [[tool.poetry.source]] table with name = "private" but no url key, or calling create_package_source({'name': 'private'}) directly. Triggered for every non-pypi source during pool construction.

Common situations: Incomplete source declaration after a copy-paste, a YAML/TOML typo (e.g. 'Url' instead of 'url'), or migrating a config that relied on an implicit URL.

Related errors


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