Graphify-Labs/graphify · error · SystemExit

ERROR: Graph is empty - extraction produced no nodes.

Error message

ERROR: Graph is empty - extraction produced no nodes.

What it means

This is not library code but the guarded build snippet embedded in graphify/skill.md (Step 4). After build_from_json() constructs the graph from .graphify_extract.json, the script checks G.number_of_nodes() and exits before ANY write if the graph is empty — so a failed or all-skipped extraction cannot clobber an existing good graph.json / GRAPH_REPORT.md / analysis sidecar (issue #1392). The message names the typical causes: everything skipped, a binary-only corpus, or extraction failure.

Source

Thrown at graphify/skill.md:419

from graphify.build import build_from_json
from graphify.cluster import cluster, score_all
from graphify.analyze import god_nodes, surprising_connections, suggest_questions
from graphify.report import generate
from graphify.export import to_json
from pathlib import Path

extraction = json.loads(Path('graphify-out/.graphify_extract.json').read_text(encoding=\"utf-8\"))
detection  = json.loads(Path('graphify-out/.graphify_detect.json').read_text(encoding=\"utf-8\"))

# root= mirrors the --update runbook (#1361): relativize source_file to the same
# base so the full build and incremental --update never drift apart on re-extract.
G = build_from_json(extraction, root='INPUT_PATH', directed=IS_DIRECTED)
# Guard BEFORE any write: an empty extraction must not clobber a good graph.json /
# GRAPH_REPORT.md / analysis sidecar. Check immediately after build (#1392).
if G.number_of_nodes() == 0:
    print('ERROR: Graph is empty - extraction produced no nodes.')
    print('Possible causes: all files were skipped, binary-only corpus, or extraction failed.')
    raise SystemExit(1)
communities = cluster(G)
cohesion = score_all(G, communities)
tokens = {'input': extraction.get('input_tokens', 0), 'output': extraction.get('output_tokens', 0)}
gods = god_nodes(G)
surprises = surprising_connections(G, communities)
labels = {cid: 'Community ' + str(cid) for cid in communities}
# Placeholder questions - regenerated with real labels in Step 5
questions = suggest_questions(G, communities, labels)

# Export FIRST and honor the #479 shrink-guard: to_json returns False (writing
# nothing) when the new graph is smaller than the existing graph.json. Only write
# GRAPH_REPORT.md + the analysis sidecar when the graph was actually written, so
# they never describe a graph that graph.json doesn't contain (#1392).
wrote = to_json(G, communities, 'graphify-out/graph.json')
if not wrote:
    print('ERROR: refused to shrink graphify-out/graph.json (existing graph has more nodes; #479).')
    print('If this shrink is intentional (you deleted files), re-run a full build with --force.')
    raise SystemExit(1)

View on GitHub (pinned to 7fe58b0b0f)

Solutions

  1. Open graphify-out/.graphify_extract.json and confirm it has entities/nodes — if not, re-run the extraction step (Step 3) for the same INPUT_PATH
  2. Check .graphifyignore patterns are not excluding everything, and confirm the input path actually contains source files
  3. If extraction genuinely found nothing to index (binary-only corpus), point /graphify at a directory with extractable text/code
  4. If extraction output looks truncated after an API failure, delete .graphify_extract.json and re-run the full extract

Example fix

before (unguarded):
G = build_from_json(extraction, root='INPUT_PATH', directed=IS_DIRECTED)
to_json(G, communities, 'graphify-out/graph.json')  # empty graph overwrites good graph.json

after (as in skill.md):
G = build_from_json(extraction, root='INPUT_PATH', directed=IS_DIRECTED)
if G.number_of_nodes() == 0:
    print('ERROR: Graph is empty - extraction produced no nodes.')
    raise SystemExit(1)
Defensive patterns

Strategy: validation

Validate before calling

extraction = json.loads(Path('graphify-out/.graphify_extract.json').read_text(encoding='utf-8'))
node_count = len(extraction.get('nodes', extraction.get('entities', [])))
if node_count == 0:
    raise SystemExit('extraction empty — fix ignore rules / corpus before building')
G = build_from_json(extraction, root='INPUT_PATH', directed=IS_DIRECTED)

Type guard

def extraction_has_nodes(extraction: dict) -> bool:
    """True when the extraction JSON carries at least one node/entity."""
    return bool(extraction.get('nodes') or extraction.get('entities'))

Prevention

When it happens

Trigger: Running the skill.md Step 4 build block when .graphify_extract.json contains no nodes: all candidate files were ignored/skipped (.graphifyignore covering everything, binary-only corpus), the LLM extraction step failed but wrote partial output, or the extraction JSON is from a different path that matched nothing.

Common situations: First run against a directory whose files are all ignored or non-source; extraction JSON left over from a run on a different INPUT_PATH; LLM extraction returned empty entities for every file; path passed with a trailing typo so nothing matched.

Related errors


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