tirth8205/code-review-graph · error · RuntimeError

the graph holds {len(file_paths)} file(s) such as {sample!r}

Error message

the graph holds {len(file_paths)} file(s) such as {sample!r}, none of them under {str(repo_root)!r}; it was built with a different repository root. Rebuild it, or retry with the root it was built with, instead of reconciling every file away.

What it means

incremental_update reconciles stored file paths against repo_root; if none of the stored files share the root's normalized prefix, it assumes the graph belongs to a different repository and aborts rather than reconciling every file away (which would empty the graph).

Source

Thrown at code_review_graph/incremental.py:1128


def _assert_graph_matches_root(repo_root: Path, store: GraphStore) -> None:
    """Refuse an incremental reconciliation anchored to a different root.

    Authoritative File nodes identify the root a graph was built with. If none
    of them are under the requested root, treating every row as stale is more
    likely to destroy a usable graph than to clean up orphan rows. Orphan-only
    databases have no File markers and retain the purge behavior from #861.
    """
    file_paths = store.get_file_marker_paths()
    if not file_paths:
        return
    prefix = normalize_file_path(repo_root)
    prefix = prefix if prefix.endswith("/") else prefix + "/"
    if any(normalize_file_path(path).startswith(prefix) for path in file_paths):
        return
    sample = normalize_file_path(sorted(file_paths)[0])
    raise RuntimeError(
        f"the graph holds {len(file_paths)} file(s) such as {sample!r}, none of "
        f"them under {str(repo_root)!r}; it was built with a different "
        "repository root. Rebuild it, or retry with the root it was built "
        "with, instead of reconciling every file away."
    )


_MAX_DEPENDENT_HOPS = int(os.environ.get("CRG_DEPENDENT_HOPS", "2"))
_MAX_DEPENDENT_FILES = 500


def _single_hop_dependents(store: GraphStore, file_path: str) -> set[str]:
    """Find files that directly depend on *file_path* (single hop)."""
    dependents: set[str] = set()
    edges = store.get_edges_by_target(file_path)
    for e in edges:
        if e.kind == "IMPORTS_FROM":
            dependents.add(e.file_path)

View on GitHub (pinned to b58668751a)

Solutions

  1. Re-run with the original root the graph was built with (shown in the message)
  2. Or rebuild the graph from scratch under the new root
  3. If the move is permanent, delete the old graph db and re-index

Example fix

# before
incremental_update(store, repo_root="/new/home/proj")
# after
incremental_update(store, repo_root="/old/home/proj")  # or rebuild index at new root
Defensive patterns

Strategy: validation

Validate before calling

stored = {normalize_file_path(p) for p in graph_store.all_file_paths()}
prefix = normalize_file_path(repo_root).rstrip("/") + "/"
if stored and not any(p.startswith(prefix) for p in stored):
    raise RuntimeError("graph root mismatch; rebuild or pass original root")

Try / catch

try:
    incremental_update(store, repo_root=root)
except RuntimeError as e:
    if "different repository root" in str(e):
        rebuild_index(root)  # full rebuild at the new root
    else:
        raise

Prevention

When it happens

Trigger: Running incremental_update(repo_root=X) when the graph was built under root Y — e.g. the repo moved, was cloned to a new path, or you passed the wrong root.

Common situations: Moving/cloning the project to a different directory, symlinks changing effective paths, or CI checking out to a different workspace path than where the index was built.

Related errors


AI-assisted analysis of tirth8205/code-review-graph@b58668751a (2026-08-28). Data as JSON: /api/errors/05a23d76c0e6895c. Report an issue: GitHub.