{"id":"6dc0e71126e52429","repo":"python-poetry/poetry","slug":"path-is-not-relative-to-any-discovered-site-typ","errorCode":null,"errorMessage":"{path} is not relative to any discovered {site_type}sites","messagePattern":"(.+?) is not relative to any discovered (.+?)sites","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/poetry/utils/env/site_packages.py","lineNumber":83,"sourceCode":"        self._writable_candidates = []\n        for candidate in self._candidates:\n            if not is_dir_writable(path=candidate, create=True):\n                continue\n            self._writable_candidates.append(candidate)\n\n        return self._writable_candidates\n\n    def make_candidates(\n        self, path: Path, writable_only: bool = False, strict: bool = False\n    ) -> list[Path]:\n        candidates = self._candidates if not writable_only else self.writable_candidates\n        if path.is_absolute():\n            for candidate in candidates:\n                with contextlib.suppress(ValueError):\n                    path.relative_to(candidate)\n                    return [path]\n            site_type = \"writable \" if writable_only else \"\"\n            raise ValueError(\n                f\"{path} is not relative to any discovered {site_type}sites\"\n            )\n\n        results = [candidate / path for candidate in candidates]\n\n        if not results and strict:\n            raise RuntimeError(\n                f'Unable to find a suitable destination for \"{path}\" in'\n                f\" {paths_csv(self._candidates)}\"\n            )\n\n        return results\n\n    def distributions(\n        self, name: str | None = None, writable_only: bool = False\n    ) -> Iterable[metadata.Distribution]:\n        path = list(\n            map(","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/python-poetry/poetry/blob/92b74dcfe348d0e01e14d40d6c1fa47a4ee04a54/src/poetry/utils/env/site_packages.py#L65-L101","documentation":"Raised as ValueError in SitePackages.make_candidates when an absolute path is passed but it is not relative to any of the discovered site-packages candidate directories (purelib/platlib/fallbacks, or the writable subset). The method requires absolute paths to live under a known site.","triggerScenarios":"Calling make_candidates(path, ...) (or a higher-level SitePackages method that delegates via _path_method_wrapper) with path.is_absolute() True, where path.relative_to(candidate) raises ValueError for every candidate. Exact branch: site_packages.py:77-85.","commonSituations":"Passing a global system path (/usr/lib/python3.11/...) to a venv-scoped SitePackages; path outside purelib/platlib; passing an absolute path when a relative package path was expected; wrong env's SitePackages instance used.","solutions":["Pass a relative path (the package subpath, e.g. 'foo/bar.py') instead of an absolute one.","Ensure the absolute path actually lives under the env's purelib or platlib.","Operate on the correct SitePackages instance for the env that owns the path.","Resolve symlinks first: Path(path).resolve() may reveal the real location under a site dir."],"exampleFix":"// before\nsite_packages.write_text(Path(\"/usr/lib/python3.11/site-packages/foo/__init__.py\"), \"\")\n# not under this env's sites -> ValueError\n\n// after - relative path under the env's site\nsite_packages.write_text(Path(\"foo/__init__.py\"), \"\")","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef path_under_a_site(path: Path, candidates: list[Path]) -> bool:\n    p = path.resolve()\n    for c in candidates:\n        try:\n            p.relative_to(c.resolve())\n            return True\n        except ValueError:\n            continue\n    return False\n\n# before calling site_packages methods with an absolute path:\nassert path_under_a_site(target, site_packages.candidates)","typeGuard":"def is_not_relative_to_sites(e: Exception) -> bool:\n    return isinstance(e, ValueError) and \"not relative to any discovered\" in str(e)","tryCatchPattern":"try:\n    site_packages._path_method_wrapper(abs_path, \"write_text\", data)\nexcept ValueError as e:\n    if \"not relative to any discovered\" in str(e):\n        # pass a relative path instead\n        site_packages.write_text(rel_path, data)\n    else:\n        raise","preventionTips":["Pass relative package subpaths to SitePackages methods, not absolute filesystem paths.","Operate on the SitePackages instance belonging to the env that owns the path.","Resolve symlinks before checking - the real target may sit under a site dir.","Validate path.relative_to(candidate) for at least one candidate before acting."],"tags":["site-packages","absolute-path","filesystem","virtualenv"],"analyzedSha":"92b74dcfe348d0e01e14d40d6c1fa47a4ee04a54","analyzedAt":"2026-08-04T20:33:34.072Z","schemaVersion":2}