Graphify-Labs/graphify · error · SystemExit

ERROR: refused to shrink graphify-out/graph.json (existing g

Error message

ERROR: refused to shrink graphify-out/graph.json (existing graph has more nodes; #479).

What it means

This is a deliberate data-integrity guard (#479) in the graphify build pipeline's export step. graphify.export.to_json() refuses to overwrite an existing graphify-out/graph.json with a smaller graph (fewer nodes), returning False without writing. The wrapper prints this ERROR and exits 1, and — by design — GRAPH_REPORT.md and .graphify_analysis.json are not written either, so no artifact ever describes a graph that graph.json does not contain (#1392).

Source

Thrown at tools/skillgen/expected/graphify__skill-copilot.md:437

    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)
report = generate(G, communities, cohesion, labels, gods, surprises, detection, tokens, 'INPUT_PATH', suggested_questions=questions)
Path('graphify-out/GRAPH_REPORT.md').write_text(report, encoding=\"utf-8\")
analysis = {
    'communities': {str(k): v for k, v in communities.items()},
    'cohesion': {str(k): v for k, v in cohesion.items()},
    'gods': gods,
    'surprises': surprises,
    'questions': questions,
}
Path('graphify-out/.graphify_analysis.json').write_text(json.dumps(analysis, indent=2, ensure_ascii=False), encoding=\"utf-8\")
print(f'Graph: {G.number_of_nodes()} nodes, {G.number_of_edges()} edges, {len(communities)} communities')
"
```

If this step prints `ERROR: Graph is empty`, stop and tell the user what happened - do not proceed to labeling or visualization.

Replace INPUT_PATH with the actual path.

View on GitHub (pinned to 7fe58b0b0f)

Solutions

  1. If the shrink is intentional, re-run a full build with --force to overwrite graph.json despite the guard.
  2. Confirm INPUT_PATH is identical to the original build root so relativization covers the same file set.
  3. Diff node counts: compare len(nodes) in graphify-out/.graphify_extract.json-derived G against graph.json to find what dropped.
  4. If graph.json is stale, remove graphify-out/ and rebuild cleanly.

Example fix

# before: refused shrink aborts the pipeline
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).')
    raise SystemExit(1)

# after: intentional shrink -> full rebuild with force
#   $(cat graphify-out/.graphify_python) build.py --force
Defensive patterns

Strategy: validation

Validate before calling

import json
from pathlib import Path

existing = Path('graphify-out/graph.json')
if existing.exists():
    old = len(json.loads(existing.read_text(encoding='utf-8')).get('nodes', []))
    if G.number_of_nodes() < old:
        print(f'shrink-guard would refuse: {old} -> {G.number_of_nodes()} nodes')
        raise SystemExit(1)

Prevention

When it happens

Trigger: to_json(G, communities, 'graphify-out/graph.json') returning False because the freshly built G has fewer nodes than the existing graph.json. Happens on re-build after source deletion, a smaller INPUT_PATH than the original build, or an extraction pass that dropped files.

Common situations: Incremental or repeated builds after codebase pruning; building from a subdirectory while graph.json came from the repo root; extraction skipping newly-binary or ignored files; stale larger graph.json from a previous branch/checkout.

Related errors


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