Graphify-Labs/graphify · error · FileNotFoundError

graph not found: {source_path}

Error message

graph not found: {source_path}

What it means

Raised by global_add when the per-repo graph file it was told to register in the global (multi-repo) graph does not exist on disk. The global graph workflow reads a previously built graphify output (e.g. graphify-out/graph.graphml) and merges it under a repo tag, so a missing source file is a hard FileNotFoundError before any manifest state is touched.

Source

Thrown at graphify/global_graph.py:88

    write_json_atomic(_GLOBAL_GRAPH, data, indent=2)


def _file_hash(path: Path) -> str:
    h = hashlib.sha256()
    h.update(path.read_bytes())
    return h.hexdigest()[:16]


def global_add(source_path: Path, repo_tag: str) -> dict:
    """Add or update a project graph in the global graph.

    Returns a summary dict with keys: repo_tag, nodes_added, nodes_removed, skipped.
    Skipped=True means the source graph hasn't changed since last add.
    """
    from graphify.build import prefix_graph_for_global, prune_repo_from_graph

    if not source_path.exists():
        raise FileNotFoundError(f"graph not found: {source_path}")

    manifest = _load_manifest()
    src_hash = _file_hash(source_path)

    existing = manifest["repos"].get(repo_tag, {})
    existing_path = existing.get("source_path", "")
    if existing_path and existing_path != str(source_path.resolve()):
        print(
            f"[graphify global] warning: repo tag '{repo_tag}' previously pointed to "
            f"{existing_path!r}, now updating to {str(source_path.resolve())!r}. "
            f"Use --as <tag> to give it a different name.",
            file=sys.stderr,
        )
    if existing.get("source_hash") == src_hash:
        return {"repo_tag": repo_tag, "nodes_added": 0, "nodes_removed": 0, "skipped": True}

    # Load source graph
    from graphify.security import check_graph_file_size_cap

View on GitHub (pinned to 7fe58b0b0f)

Solutions

  1. Build the repo graph first: `graphify build .` in that repo, then re-run the global add pointing at the generated file
  2. Check the path: `ls graphify-out/` and pass the actual graph file (commonly graphify-out/graph.graphml)
  3. Use an absolute path to avoid cwd-dependent resolution

Example fix

# before
graphify global add graph.graphml --as myrepo   # FileNotFoundError: graph not found

# after
graphify build .
graphify global add graphify-out/graph.graphml --as myrepo
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

src = Path("graphify-out/graph.graphml").resolve()
if not src.exists():
    raise SystemExit(f"build the repo graph first - {src} not found")

from graphify.global_graph import global_add
global_add(src, repo_tag="myrepo")

Try / catch

try:
    global_add(src, repo_tag)
except FileNotFoundError as e:
    if "graph not found" in str(e):
        subprocess.check_call(["graphify", "build", "."])
        global_add(src, repo_tag)
    else:
        raise

Prevention

When it happens

Trigger: Calling global_add(source_path, repo_tag) — e.g. `graphify global add graphify-out/graph.graphml` — where source_path.exists() is False: wrong path, graph not built yet, or running from a directory where the relative path doesn't resolve.

Common situations: Running `graphify global add` before `graphify build` in a fresh clone; passing the repo root instead of the .graphml output; path typos or shell quoting; running the command from a different cwd with a relative path.

Related errors


AI-assisted analysis of Graphify-Labs/graphify@7fe58b0b0f (2026-08-14). Data as JSON: /api/errors/e427c44db6374c0e. Report an issue: GitHub.