{"id":"7ed10cef8634a59f","repo":"sqlalchemy/alembic","slug":"path-is-not-in-the-same-subtree-as-other","errorCode":null,"errorMessage":"{path} is not in the same subtree as {other}","messagePattern":"(.+?) is not in the same subtree as (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"alembic/util/compat.py","lineNumber":88,"sourceCode":"    ) -> Path:\n        \"\"\"\n        Calculate the relative path of 'path' with respect to 'other',\n        optionally allowing 'path' to be outside the subtree of 'other'.\n\n        OK I used AI for this, sorry\n\n        \"\"\"\n        try:\n            return path.relative_to(other)\n        except ValueError:\n            if walk_up:\n                other_ancestors = list(other.parents) + [other]\n                for ancestor in other_ancestors:\n                    try:\n                        return path.relative_to(ancestor)\n                    except ValueError:\n                        continue\n                raise ValueError(\n                    f\"{path} is not in the same subtree as {other}\"\n                )\n            else:\n                raise\n\n\ndef importlib_metadata_get(group: str) -> Sequence[EntryPoint]:\n    \"\"\"provide a facade for metadata.entry_points().\n\n    This is no longer a \"compat\" function as of Python 3.10, however\n    the function is widely referenced in the test suite and elsewhere so is\n    still in this module for compatibility reasons.\n\n    \"\"\"\n    return metadata.entry_points().select(group=group)\n\n\ndef formatannotation_fwdref(","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/sqlalchemy/alembic/blob/44fb3450330204b222ff05135e1fbbbdb28c44db/alembic/util/compat.py#L70-L106","documentation":"Raised inside path_relative_to (alembic/util/compat.py:88) when walk_up=True and the given path shares no common ancestor directory with 'other' — i.e. after walking every parent of 'other', path.relative_to still fails for all of them. This is Alembic's backport of pathlib's walk_up behavior; on paths with no shared root (e.g. different drives on Windows, or mismatched Path types) it gives up.","triggerScenarios":"Calling path_relative_to(path_a, path_b, walk_up=True) where path_a and path_b live on entirely disjoint roots (e.g. C:\\proj vs D:\\other on Windows, or a posix path vs a windows path in tests). Also reachable via Alembic internals that compute template/resource paths across different roots.","commonSituations":"Windows multi-drive setups where the migrations directory and the alembic package install are on different drive letters; cross-platform test suites that construct mixed-style Path objects; symlinks that resolve to a different filesystem root.","solutions":["Confirm both paths are under the same filesystem root; if on Windows, move both under the same drive letter.","Avoid passing walk_up=True when the paths are known to be unrelated; compute the relationship manually instead.","Use absolute, normalized paths resolved via Path.resolve() before comparison to eliminate symlink/junction ambiguity."],"exampleFix":"# before: paths on different roots\nrel = path_relative_to(Path('/mnt/data/x'), Path('/opt/app'), walk_up=True)\n# after: ensure both share a common root, or compute manually\nrel = Path('/opt/app/data/x').relative_to(Path('/opt/app'))","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef safe_relative(path: Path, other: Path) -> Path:\n    path, other = path.resolve(), other.resolve()\n    try:\n        return path.relative_to(other)\n    except ValueError:\n        # only call path_relative_to(walk_up=True) when roots match\n        if path.anchor != other.anchor:\n            raise ValueError(f'{path} and {other} are on different roots')\n        from alembic.util.compat import path_relative_to\n        return path_relative_to(path, other, walk_up=True)","typeGuard":"from pathlib import PurePath\ndef shares_root(a: PurePath, b: PurePath) -> bool:\n    return PurePath(a).anchor == PurePath(b).anchor","tryCatchPattern":"from alembic.util.compat import path_relative_to\ntry:\n    rel = path_relative_to(path, other, walk_up=True)\nexcept ValueError as e:\n    # fall back to absolute path string if no common subtree\n    rel = path","preventionTips":["Resolve both paths via Path.resolve() before comparing to eliminate symlink/junction noise.","On Windows, keep project files and dependencies on the same drive letter.","Prefer plain relative_to() when paths are expected to be nested."],"tags":["alembic","path","filesystem","compat","cross-platform"],"analyzedSha":"44fb3450330204b222ff05135e1fbbbdb28c44db","analyzedAt":"2026-08-04T19:57:10.248Z","schemaVersion":2}