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
- Confirm graphify-out/.graphify_extract.json has a non-empty nodes array; re-run extraction if not.
- Check the detection sidecar (.graphify_detect.json) for what was skipped and why; ensure the target tree contains text source files.
- Remove the stale extract/detect sidecars and re-run the full build so empty artifacts are not carried forward.
- 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
- Assert the extraction sidecar is non-empty before building.
- Run the skill from the repository root so INPUT_PATH and sidecar paths resolve correctly.
- Ensure the target tree has extractable text files and skip rules are not over-broad.
- Clear sidecars when changing the input path.
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
- module 'graphify' has no attribute {name!r}
- ERROR: invalid JSON in {path}: {exc}
- --cargo on Python 3.10 needs tomli. Install with: pip instal
- ERROR: Graph is empty - extraction produced no nodes.
- ERROR: Graph is empty - extraction produced no nodes.
AI-assisted analysis of Graphify-Labs/graphify@7fe58b0b0f (2026-08-14).
Data as JSON: /api/errors/9178f62795ab6dff.
Report an issue: GitHub.