{"record":{"id":"00e805d1e65bad6e","repo":"Graphify-Labs/graphify","slug":"all-community-node-ids-are-stale-none-exist-in-t","errorCode":null,"errorMessage":"all community node IDs are stale — none exist in the graph. Re-run `graphify extract .` to regenerate .graphify_analysis.json.","messagePattern":"all community node IDs are stale — none exist in the graph\\. Re-run `graphify extract \\.` to regenerate \\.graphify_analysis\\.json\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"graphify/wiki.py","lineNumber":266,"sourceCode":"    # Filter stale node IDs that exist in communities but not in G.\n    # Analysis JSON can drift from the graph after dedup / re-extract / update.\n    # NetworkX 3.x returns DegreeView({}) for missing nodes instead of raising,\n    # which crashes sorted() with TypeError; G.neighbors()/G.nodes[] also raise.\n    import sys as _sys\n    _g_nodes = set(G.nodes)\n    _orig_total = sum(len(ns) for ns in communities.values())\n    communities = {cid: [n for n in nodes if n in _g_nodes] for cid, nodes in communities.items()}\n    communities = {cid: nodes for cid, nodes in communities.items() if nodes}\n    _kept_total = sum(len(ns) for ns in communities.values())\n    if _kept_total < _orig_total:\n        print(\n            f\"wiki: dropped {_orig_total - _kept_total} stale node ID(s) not in graph \"\n            f\"({len(communities)} communities remaining)\",\n            file=_sys.stderr,\n        )\n\n    if not communities:\n        raise ValueError(\n            \"all community node IDs are stale — none exist in the graph. \"\n            \"Re-run `graphify extract .` to regenerate .graphify_analysis.json.\"\n        )\n\n    # Clear stale .md files from previous runs to prevent orphan accumulation.\n    # Community labels are LLM-generated (per skill.md Step 5) and non-deterministic\n    # across runs — the same conceptual community may be named differently each time\n    # (e.g. \"AutoAgent Skills\" → \"AutoAgent Methodology\"), leaving the previous file\n    # as an orphan. Since to_wiki() owns wiki/ entirely (always writes the full set),\n    # it can safely clear .md files at the start of each call.\n    for old_article in out.glob(\"*.md\"):\n        old_article.unlink()\n\n    labels = community_labels or {cid: f\"Community {cid}\" for cid in communities}\n    cohesion = cohesion or {}\n    god_nodes_data = god_nodes_data or []\n\n    # Build node->community lookup once; node attrs never carry community (it lives in","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/Graphify-Labs/graphify/blob/7fe58b0b0f3873be9a21c30106b8b8527c353aa6/graphify/wiki.py#L248-L284","documentation":"graphify.wiki.to_wiki() filters the communities dict against the current graph's node set before rendering, because analysis JSON can drift from G after dedup, re-extraction, or incremental updates (NetworkX 3.x returns empty DegreeViews for missing nodes instead of raising, which would crash sorted()). After filtering, if not a single node ID from the communities dict exists in G, every community became empty and the code raises this ValueError rather than clearing wiki/ for nothing. The message tells you the sidecar and the graph are fully out of sync.","triggerScenarios":"Calling to_wiki(G, communities) where every node ID listed in communities is absent from G.nodes — e.g. G was rebuilt from scratch (new stable node IDs/hashes) while .graphify_analysis.json still holds node IDs from an older extraction; or node dedup renamed/merged all old IDs. A stderr warning ('wiki: dropped N stale node ID(s)…') precedes the raise.","commonSituations":"Re-running `graphify extract .` after large refactors or file renames, then feeding the fresh graph together with a stale .graphify_analysis.json from a previous run; mixing artifacts from a full build and an incremental --update run.","solutions":["Re-run `graphify extract .` to regenerate .graphify_analysis.json so its node IDs match the current graph","If artifacts came from different runs, do a clean full rebuild (delete graphify-out/ sidecars first) so graph.json and .graphify_analysis.json are produced by the same extraction","If you build G yourself, confirm you are loading the same graph.json the communities were clustered from (check node-count and a sample node ID against set(G.nodes))"],"exampleFix":"# before\nG = load_graph('graphify-out/graph.json')\ncommunities = json.loads(Path('graphify-out/.graphify_analysis.json').read_text())['communities']\nto_wiki(G, communities, 'graphify-out/wiki')  # ValueError: all stale\n\n# after\nimport subprocess, sys\n_g_nodes = set(G.nodes)\n_ids = {n for ns in communities.values() for n in ns}\nif not _ids & _g_nodes:\n    sys.exit('analysis JSON fully stale — re-run `graphify extract .`')\nto_wiki(G, communities, 'graphify-out/wiki')","handlingStrategy":"validation","validationCode":"analysis = json.loads(Path('graphify-out/.graphify_analysis.json').read_text(encoding='utf-8'))\ncommunities = analysis['communities']\n_g_nodes = set(G.nodes)\n_known = {n for members in communities.values() for n in members} & _g_nodes\nif not _known:\n    raise SystemExit('analysis JSON is fully stale — re-run `graphify extract .` before to_wiki')\n\nto_wiki(G, communities, 'graphify-out/wiki')","typeGuard":"def communities_match_graph(communities: dict, G) -> bool:\n    \"\"\"True when at least one community node ID exists in G.\"\"\"\n    nodes = set(G.nodes)\n    return any(n in nodes for members in communities.values() for n in members)","tryCatchPattern":"try:\n    to_wiki(G, communities, 'graphify-out/wiki')\nexcept ValueError as e:\n    if 'stale' in str(e):\n        raise SystemExit('sidecar and graph are out of sync — full re-extract required') from e\n    raise","preventionTips":["Always regenerate .graphify_analysis.json in the same run that writes graph.json","After dedup/rename-heavy refactors, do a clean full rebuild instead of mixing old sidecars with a new graph","Watch for the 'wiki: dropped N stale node ID(s)' stderr warning — it is the early signal before the hard failure"],"tags":["python","data-integrity","stale-state","graphify","wiki"],"backgroundTag":null,"analyzedSha":"7fe58b0b0f3873be9a21c30106b8b8527c353aa6","analyzedAt":"2026-08-14T19:23:21.323Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}