Graphify-Labs/graphify · error · SystemExit

ERROR: graph file must contain a JSON object: {path}

Error message

ERROR: graph file must contain a JSON object: {path}

What it means

Empty-graph guard in the aider-flavored fragment (tools/skillgen/fragments/core/aider.md:412). Unlike the newer core fragment, this variant reads .graphify_extract.json from the CURRENT directory (Path('.graphify_extract.json'), no graphify-out/ prefix) and calls build_from_json(extraction, directed=IS_DIRECTED) without root=. Zero nodes abort with SystemExit(1) before any write (#1392).

Source

Thrown at graphify/callflow_html.py:275

        edge = dict(attrs)
        edge["source"] = edge.get("_src", edge.get("source", source))
        edge["target"] = edge.get("_tgt", edge.get("target", target))
        edge.setdefault("id", f"edge_{index}")
        edges.append(edge)
    return nodes, edges


def load_graph(path: str | Path) -> tuple:
    """Load graph.json. Returns normalized (nodes, edges, hyperedges, metadata)."""
    if path:
        from graphify.security import check_graph_file_size_cap
        try:
            check_graph_file_size_cap(Path(path))
        except ValueError as exc:
            raise SystemExit(f"ERROR: {exc}") from exc
    data = read_json(path)
    if not isinstance(data, dict):
        raise SystemExit(f"ERROR: graph file must contain a JSON object: {path}")

    graph_block = data.get("graph") if isinstance(data.get("graph"), dict) else {}
    meta_block = data.get("metadata") if isinstance(data.get("metadata"), dict) else {}

    node_link = _node_link_payload(data)
    if node_link:
        raw_nodes, raw_edges = node_link
    else:
        raw_nodes = first_list(data.get("nodes"), data.get("vertices"), graph_block.get("nodes"), graph_block.get("vertices"))
        raw_edges = first_list(data.get("links"), data.get("edges"), graph_block.get("links"), graph_block.get("edges"))
    hyperedges = first_list(data.get("hyperedges"), graph_block.get("hyperedges"), data.get("groups"), graph_block.get("groups"))

    nodes = [normalize_node(n, i) for i, n in enumerate(raw_nodes) if isinstance(n, dict)]
    edges = []
    for i, raw_edge in enumerate(raw_edges):
        if not isinstance(raw_edge, dict):
            continue
        edge = normalize_edge(raw_edge, i)

View on GitHub (pinned to 7fe58b0b0f)

Solutions

  1. Check that .graphify_extract.json in the CURRENT directory has a non-empty nodes array; if it is stale or from another run, delete it.
  2. Run the pipeline from the directory where extraction actually wrote its sidecars, or update to the newer fragment that reads graphify-out/ prefixed paths.
  3. Re-run extraction on a corpus with extractable text files; inspect .graphify_detect.json for skip reasons.
  4. Verify the extraction stage completed successfully (token counts, logs) before the build step.

Example fix

# before: cwd-sidecar path resolves to an empty legacy file
Path('.graphify_extract.json')  # empty -> 0 nodes

# after: read from the canonical output dir
extraction = json.loads(Path('graphify-out/.graphify_extract.json').read_text(encoding='utf-8'))
Defensive patterns

Strategy: validation

Validate before calling

import json
from pathlib import Path

# this legacy fragment reads cwd-relative sidecars - check BOTH locations
for p in (Path('.graphify_extract.json'), Path('graphify-out/.graphify_extract.json')):
    if p.exists():
        nodes = json.loads(p.read_text()).get('nodes') or []
        print(f'{p}: {len(nodes)} nodes')
        if not nodes:
            raise SystemExit(f'{p} is empty - delete it or re-run extraction')

Prevention

When it happens

Trigger: build_from_json() on the extraction JSON yields 0 nodes: empty nodes array after extraction, all files skipped, or the extraction stage failed. Additionally, because sidecars are read from cwd rather than graphify-out/, running from a directory that contains a stale/empty .graphify_extract.json triggers it even when a good extraction exists elsewhere.

Common situations: Running the aider workflow from a subdirectory so .graphify_extract.json resolves to the wrong file; legacy layout where sidecars lived at repo root; binary-only or fully-skipped corpus; silent upstream extraction failure.

Related errors


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