sqlalchemy/alembic · error · ValueError

{path} is not in the same subtree as {other}

Error message

{path} is not in the same subtree as {other}

What it means

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.

Source

Thrown at alembic/util/compat.py:88

    ) -> Path:
        """
        Calculate the relative path of 'path' with respect to 'other',
        optionally allowing 'path' to be outside the subtree of 'other'.

        OK I used AI for this, sorry

        """
        try:
            return path.relative_to(other)
        except ValueError:
            if walk_up:
                other_ancestors = list(other.parents) + [other]
                for ancestor in other_ancestors:
                    try:
                        return path.relative_to(ancestor)
                    except ValueError:
                        continue
                raise ValueError(
                    f"{path} is not in the same subtree as {other}"
                )
            else:
                raise


def importlib_metadata_get(group: str) -> Sequence[EntryPoint]:
    """provide a facade for metadata.entry_points().

    This is no longer a "compat" function as of Python 3.10, however
    the function is widely referenced in the test suite and elsewhere so is
    still in this module for compatibility reasons.

    """
    return metadata.entry_points().select(group=group)


def formatannotation_fwdref(

View on GitHub (pinned to 44fb345033)

Solutions

  1. Confirm both paths are under the same filesystem root; if on Windows, move both under the same drive letter.
  2. Avoid passing walk_up=True when the paths are known to be unrelated; compute the relationship manually instead.
  3. Use absolute, normalized paths resolved via Path.resolve() before comparison to eliminate symlink/junction ambiguity.

Example fix

# before: paths on different roots
rel = path_relative_to(Path('/mnt/data/x'), Path('/opt/app'), walk_up=True)
# after: ensure both share a common root, or compute manually
rel = Path('/opt/app/data/x').relative_to(Path('/opt/app'))
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def safe_relative(path: Path, other: Path) -> Path:
    path, other = path.resolve(), other.resolve()
    try:
        return path.relative_to(other)
    except ValueError:
        # only call path_relative_to(walk_up=True) when roots match
        if path.anchor != other.anchor:
            raise ValueError(f'{path} and {other} are on different roots')
        from alembic.util.compat import path_relative_to
        return path_relative_to(path, other, walk_up=True)

Type guard

from pathlib import PurePath
def shares_root(a: PurePath, b: PurePath) -> bool:
    return PurePath(a).anchor == PurePath(b).anchor

Try / catch

from alembic.util.compat import path_relative_to
try:
    rel = path_relative_to(path, other, walk_up=True)
except ValueError as e:
    # fall back to absolute path string if no common subtree
    rel = path

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of sqlalchemy/alembic@44fb345033 (2026-08-04). Data as JSON: /data/errors/7ed10cef8634a59f.json. Report an issue: GitHub.