Graphify-Labs/graphify · error · RuntimeError

Cannot read {graph_path} for incremental merge: {exc}. Delet

Error message

Cannot read {graph_path} for incremental merge: {exc}. Delete the file and run a full rebuild.

What it means

The generic (cross-platform) graphify skill template's empty-graph guard (tools/skillgen/expected/graphify__skill.md:419). Immediately after build_from_json() constructs the networkx graph from .graphify_extract.json, a zero node count aborts with SystemExit(1) before cluster(), to_json(), or any file write runs — so a bad extraction cannot destroy existing outputs (#1392).

Source

Thrown at graphify/build.py:1432

    The latter rebuilds an undirected nx.Graph and then enumerating
    edges() yields endpoints based on node insertion order, which
    silently flips directional edges (e.g. `calls`) when the callee
    was inserted before the caller. The _src/_tgt direction-preserving
    attrs are popped before saving in export.py, so going through the
    NetworkX round-trip loses direction permanently (#760).

    Returns None when the file does not exist. Raises RuntimeError when it
    exists but cannot be parsed — callers must refuse to overwrite rather
    than silently replace a possibly-recoverable graph.
    """
    if not graph_path.exists():
        return None
    from graphify.security import check_graph_file_size_cap
    check_graph_file_size_cap(graph_path)
    try:
        data = json.loads(graph_path.read_text(encoding="utf-8"))
    except (json.JSONDecodeError, OSError) as exc:
        raise RuntimeError(
            f"Cannot read {graph_path} for incremental merge: {exc}. "
            "Delete the file and run a full rebuild."
        ) from exc
    links_key = "links" if "links" in data else "edges"
    nodes = list(data.get("nodes", []))
    edges = list(data.get(links_key, []))
    # Backfill tier provenance on legacy items (#2334): _origin is stamped at
    # extraction time only (extract.py for AST, and the semantic path never
    # stamps), so pre-0.9.16 graphs and externally-merged fragments carry
    # unstamped items. Stamp them via the _is_ast_tier shape fallback so the
    # graph self-heals on the next write and every downstream tier decision
    # (build_merge replace, watch reconcile) reads an explicit marker.
    for item in nodes:
        if isinstance(item, dict):
            item.setdefault("_origin", "ast" if _is_ast_tier(item) else "semantic")
    for item in edges:
        if isinstance(item, dict):
            item.setdefault("_origin", "ast" if _is_ast_tier(item) else "semantic")

View on GitHub (pinned to 7fe58b0b0f)

Solutions

  1. Confirm graphify-out/.graphify_extract.json has a non-empty nodes array; re-run extraction if not.
  2. Check the detection sidecar (.graphify_detect.json) for what was skipped and why; ensure the target tree contains text source files.
  3. Remove the stale extract/detect sidecars and re-run the full build so empty artifacts are not carried forward.
  4. Run from the repository root (or the directory the skill expects) so INPUT_PATH resolves to the intended tree.

Example fix

# before
/graphify ./build-output   # binary-only, zero nodes

# after
rm graphify-out/.graphify_extract.json graphify-out/.graphify_detect.json
/graphify ./src
Defensive patterns

Strategy: validation

Validate before calling

import json
from pathlib import Path

extract = json.loads(Path('graphify-out/.graphify_extract.json').read_text(encoding='utf-8'))
assert extract.get('nodes'), 'empty nodes list - abort before build_from_json'
print('precheck passed:', len(extract['nodes']), 'nodes')

Prevention

When it happens

Trigger: build_from_json(extraction, root='INPUT_PATH', directed=IS_DIRECTED) returns a graph with 0 nodes: the extraction JSON has an empty node list, all input files were skipped during detection, or extraction itself failed silently upstream.

Common situations: Running /graphify on an empty or binary-only directory; a previous pipeline step crashed after truncating .graphify_extract.json to an empty structure; over-aggressive skip/exclude rules; wrong working directory so relative INPUT_PATH resolves to nothing.

Related errors


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