{"id":"c9dde13203e739b7","repo":"python-poetry/poetry","slug":"missing-url-in-source-name-r","errorCode":null,"errorMessage":"Missing [url] in source {name!r}.","messagePattern":"Missing \\[url\\] in source (.+?)\\.","errorType":"validation","errorClass":"InvalidSourceError","httpStatus":null,"severity":"error","filePath":"src/poetry/factory.py","lineNumber":235,"sourceCode":"            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\n        return repository_class(\n            name,\n            url,\n            config=config,\n            disable_cache=disable_cache,\n            pool_size=pool_size,\n        )\n\n    @classmethod\n    def create_legacy_pyproject_from_package(cls, package: Package) -> TOMLDocument:\n        import tomlkit\n","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/python-poetry/poetry/blob/92b74dcfe348d0e01e14d40d6c1fa47a4ee04a54/src/poetry/factory.py#L217-L253","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add url = \"https://...\" to the [[tool.poetry.source]] table named in the message.","Verify with: poetry source show — it lists parsed sources and reveals the missing url.","Check for typos in the key name (TOML is case-sensitive: it must be lowercase 'url')."],"exampleFix":"# before\n[[tool.poetry.source]]\nname = \"private\"\n\n# after\n[[tool.poetry.source]]\nname = \"private\"\nurl = \"https://repo.example.com/simple\"","handlingStrategy":"validation","validationCode":"def validate_source(source: dict) -> None:\n    name = source.get('name')\n    if not name:\n        raise ValueError('Missing [name] in source.')\n    if name.lower() != 'pypi' and 'url' not in source:\n        raise ValueError(f\"Missing [url] in source {name!r}.\")","typeGuard":null,"tryCatchPattern":"from poetry.repositories.exceptions import InvalidSourceError\n\ntry:\n    Factory.create_package_source(source, config)\nexcept InvalidSourceError as e:\n    if 'Missing [url]' in str(e):\n        raise SystemExit(f'Configuration error: {e}. Add a url to the source.')","preventionTips":["Always pair name + url in [[tool.poetry.source]] tables.","Run `poetry source show` after editing sources to validate parsing."],"tags":["configuration","source-repository","pyproject","validation"],"analyzedSha":"92b74dcfe348d0e01e14d40d6c1fa47a4ee04a54","analyzedAt":"2026-08-04T20:33:34.072Z","schemaVersion":2}