{"record":{"id":"5a9a2f2c8efe66dc","repo":"Graphify-Labs/graphify","slug":"error-graph-is-empty-extraction-produced-no-nod-5a9a2f","errorCode":null,"errorMessage":"ERROR: Graph is empty - extraction produced no nodes.","messagePattern":"ERROR: Graph is empty - extraction produced no nodes\\.","errorType":"console","errorClass":"SystemExit","httpStatus":null,"severity":"error","filePath":"tools/skillgen/expected/graphify__skill-aider.md","lineNumber":412,"sourceCode":"$(cat graphify-out/.graphify_python) -c \"\nimport sys, json\nfrom graphify.build import build_from_json\nfrom graphify.cluster import cluster, score_all\nfrom graphify.analyze import god_nodes, surprising_connections, suggest_questions\nfrom graphify.report import generate\nfrom graphify.export import to_json\nfrom pathlib import Path\n\nextraction = json.loads(Path('.graphify_extract.json').read_text())\ndetection  = json.loads(Path('.graphify_detect.json').read_text())\n\nG = build_from_json(extraction, directed=IS_DIRECTED)\n# Guard BEFORE any write: an empty extraction must not clobber a good graph.json /\n# GRAPH_REPORT.md / analysis sidecar. Check immediately after build (#1392).\nif G.number_of_nodes() == 0:\n    print('ERROR: Graph is empty - extraction produced no nodes.')\n    print('Possible causes: all files were skipped, binary-only corpus, or extraction failed.')\n    raise SystemExit(1)\ncommunities = cluster(G)\ncohesion = score_all(G, communities)\ntokens = {'input': extraction.get('input_tokens', 0), 'output': extraction.get('output_tokens', 0)}\ngods = god_nodes(G)\nsurprises = surprising_connections(G, communities)\nlabels = {cid: 'Community ' + str(cid) for cid in communities}\n# Placeholder questions - regenerated with real labels in Step 5\nquestions = suggest_questions(G, communities, labels)\n\n# Persist the graph first and only write the report/analysis if it actually\n# persisted - to_json refuses to shrink an existing graph.json (#479), and a\n# report describing a graph we did not write would be a lie (#1392).\nwrote = to_json(G, communities, 'graphify-out/graph.json')\nif not wrote:\n    print('ERROR: refused to shrink graphify-out/graph.json (fewer nodes than the existing graph). Run a full rebuild to be safe.')\n    raise SystemExit(1)\nreport = generate(G, communities, cohesion, labels, gods, surprises, detection, tokens, 'INPUT_PATH', suggested_questions=questions)\nPath('graphify-out/GRAPH_REPORT.md').write_text(report)","sourceCodeStart":394,"sourceCodeEnd":430,"githubUrl":"https://github.com/Graphify-Labs/graphify/blob/7fe58b0b0f3873be9a21c30106b8b8527c353aa6/tools/skillgen/expected/graphify__skill-aider.md#L394-L430","documentation":"Identical empty-graph guard to skill.md's, but in the generated artifact tools/skillgen/expected/graphify__skill-aider.md (the 'aider' host render of the graphify skill). The Step 4 build block checks G.number_of_nodes() immediately after build_from_json() and SystemExits before any persistence write, protecting existing graph.json / report / analysis from being clobbered by an empty extraction (#1392). This older expected-render variant reads .graphify_extract.json from the working directory and writes the sidecar as .graphify_analysis.json.","triggerScenarios":"Executing the aider skill's Step 4 when the loaded .graphify_extract.json yields zero nodes — all files skipped by ignore rules, binary-only corpus, or a failed/truncated extraction JSON.","commonSituations":"Running the aider-rendered skill on an empty or fully-ignored directory; stale extract JSON from a different input path; LLM extraction returned nothing but still wrote the file.","solutions":["Re-run the extraction step (Step 3) for the intended path and verify .graphify_extract.json contains nodes/entities","Verify the input directory contains extractable text/code files and .graphifyignore is not excluding everything","Delete a truncated .graphify_extract.json and re-extract from scratch"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"extraction = json.loads(Path('.graphify_extract.json').read_text())\nif not extraction.get('nodes') and not extraction.get('entities'):\n    raise SystemExit('extraction produced nothing — re-run Step 3 before building')\nG = build_from_json(extraction, directed=IS_DIRECTED)","typeGuard":"def extraction_has_nodes(extraction: dict) -> bool:\n    return bool(extraction.get('nodes') or extraction.get('entities'))","tryCatchPattern":null,"preventionTips":["Check the extraction JSON for content before running the aider skill's build block","Keep input corpus and .graphifyignore stable between extraction and build steps","Abort the extraction step itself on empty results so downstream steps never run"],"tags":["graphify","generated-skill","guard","empty-state","aider"],"backgroundTag":null,"analyzedSha":"7fe58b0b0f3873be9a21c30106b8b8527c353aa6","analyzedAt":"2026-08-14T19:23:21.323Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}