{"record":{"id":"91e228af85733313","repo":"pypa/pip","slug":"directory-entries-are-not-supported-in-remote-pylo","errorCode":null,"errorMessage":"Directory entries are not supported in remote pylock.toml {pylock_path_or_url!r}","messagePattern":"Directory entries are not supported in remote pylock\\.toml (.+?)","errorType":"exception","errorClass":"InstallationError","httpStatus":null,"severity":"error","filePath":"src/pip/_internal/utils/pylock.py","lineNumber":224,"sourceCode":") -> str:\n    url = _package_dist_url(\n        pylock_path_or_url, package_archive.path, package_archive.url\n    )\n    if package_archive.subdirectory:\n        if \"#\" in url:\n            raise InstallationError(\n                f\"Package URL {url!r} cannot contain fragments in combination \"\n                f\"with subdirectory field (in {pylock_path_or_url!r})\"\n            )\n        url += \"#subdirectory=\" + package_archive.subdirectory\n    return url\n\n\ndef package_directory_requirement_url(\n    pylock_path_or_url: str, package_directory: PackageDirectory\n) -> str:\n    if _is_url(pylock_path_or_url) and not pylock_path_or_url.startswith(\"file://\"):\n        raise InstallationError(\n            f\"Directory entries are not supported in remote pylock.toml \"\n            f\"{pylock_path_or_url!r}\"\n        )\n    url = _package_dist_url(pylock_path_or_url, package_directory.path, None)\n    assert url.startswith(\"file://\")\n    if not url.endswith(\"/\"):\n        url += \"/\"\n    if package_directory.subdirectory:\n        url += package_directory.subdirectory\n        if not url.endswith(\"/\"):\n            url += \"/\"\n    return url\n\n\ndef package_sdist_requirement_url(\n    pylock_path_or_url: str, package_sdist: PackageSdist\n) -> str:\n    return _package_dist_url(pylock_path_or_url, package_sdist.path, package_sdist.url)","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_internal/utils/pylock.py#L206-L242","documentation":"Raised as InstallationError by package_directory_requirement_url (pylock.py:224) when a pylock file loaded from a remote (non-file://) URL contains a package entry of type directory. Directory entries reference local filesystem directories, which only make sense for local lock files. A directory entry in a remote lock file would point to a path on the downloader's machine, which is meaningless or a security risk. The check at line 223 rejects any pylock URL that _is_url and doesn't start with file://.","triggerScenarios":"Loading a pylock.toml from https:// or http:// that contains a [[packages]] entry with a `directory` field (PackageDirectory). The guard at line 223 detects the remote non-file URL and raises.","commonSituations":"A local lock file (with directory entries) uploaded to a web server or artifact store and then referenced by URL. Lock files generated for monorepo local-development that are accidentally distributed as remote locks.","solutions":["Convert the directory entry to an archive, sdist, or wheel entry with a downloadable URL.","Download the pylock.toml to a local path and reference it by path instead of URL.","Use a file:// URL if the directory is accessible on the local filesystem.","Regenerate the lock file from a clean checkout and replace local directory references with published artifacts."],"exampleFix":"// before (pylock at https://example.com/lock.toml)\n[[packages]]\nname = \"mylib\"\n[packages.directory]\npath = \"./mylib\"\n\n// after\n# Download lock locally first:\n$ pip install -r ./lock.toml","handlingStrategy":"validation","validationCode":"def is_remote_non_file_url(url: str) -> bool:\n    \"\"\"True if the pylock source is a remote URL (directory entries unsafe).\"\"\"\n    lowered = url.lower()\n    if lowered.startswith('file://'):\n        return False\n    return lowered.startswith('http://') or lowered.startswith('https://')\n\n# Before installing from a remote pylock, scan for directory entries\n# and reject or convert them to archive/wheel entries.","typeGuard":"def allows_directory_entries(pylock_source: str) -> bool:\n    \"\"\"True if the pylock source allows directory package entries (local only).\"\"\"\n    return not (\n        pylock_source.lower().startswith(('http://', 'https://'))\n    )","tryCatchPattern":null,"preventionTips":["Do not publish lock files with directory entries to web servers; use local paths.","Convert local directory dependencies to published archives/wheels before distributing lock files.","Use file:// URLs for local lock files that need directory entries."],"tags":["pylock","directory-entry","remote-lock","validation"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}