Graphify-Labs/graphify · error · ValueError
all community node IDs are stale — none exist in the graph.
Error message
all community node IDs are stale — none exist in the graph. Re-run `graphify extract .` to regenerate .graphify_analysis.json.
What it means
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.
Source
Thrown at graphify/wiki.py:266
# Filter stale node IDs that exist in communities but not in G.
# Analysis JSON can drift from the graph after dedup / re-extract / update.
# NetworkX 3.x returns DegreeView({}) for missing nodes instead of raising,
# which crashes sorted() with TypeError; G.neighbors()/G.nodes[] also raise.
import sys as _sys
_g_nodes = set(G.nodes)
_orig_total = sum(len(ns) for ns in communities.values())
communities = {cid: [n for n in nodes if n in _g_nodes] for cid, nodes in communities.items()}
communities = {cid: nodes for cid, nodes in communities.items() if nodes}
_kept_total = sum(len(ns) for ns in communities.values())
if _kept_total < _orig_total:
print(
f"wiki: dropped {_orig_total - _kept_total} stale node ID(s) not in graph "
f"({len(communities)} communities remaining)",
file=_sys.stderr,
)
if not communities:
raise ValueError(
"all community node IDs are stale — none exist in the graph. "
"Re-run `graphify extract .` to regenerate .graphify_analysis.json."
)
# Clear stale .md files from previous runs to prevent orphan accumulation.
# Community labels are LLM-generated (per skill.md Step 5) and non-deterministic
# across runs — the same conceptual community may be named differently each time
# (e.g. "AutoAgent Skills" → "AutoAgent Methodology"), leaving the previous file
# as an orphan. Since to_wiki() owns wiki/ entirely (always writes the full set),
# it can safely clear .md files at the start of each call.
for old_article in out.glob("*.md"):
old_article.unlink()
labels = community_labels or {cid: f"Community {cid}" for cid in communities}
cohesion = cohesion or {}
god_nodes_data = god_nodes_data or []
# Build node->community lookup once; node attrs never carry community (it lives inView on GitHub (pinned to 7fe58b0b0f)
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))
Example fix
# before
G = load_graph('graphify-out/graph.json')
communities = json.loads(Path('graphify-out/.graphify_analysis.json').read_text())['communities']
to_wiki(G, communities, 'graphify-out/wiki') # ValueError: all stale
# after
import subprocess, sys
_g_nodes = set(G.nodes)
_ids = {n for ns in communities.values() for n in ns}
if not _ids & _g_nodes:
sys.exit('analysis JSON fully stale — re-run `graphify extract .`')
to_wiki(G, communities, 'graphify-out/wiki') Defensive patterns
Strategy: validation
Validate before calling
analysis = json.loads(Path('graphify-out/.graphify_analysis.json').read_text(encoding='utf-8'))
communities = analysis['communities']
_g_nodes = set(G.nodes)
_known = {n for members in communities.values() for n in members} & _g_nodes
if not _known:
raise SystemExit('analysis JSON is fully stale — re-run `graphify extract .` before to_wiki')
to_wiki(G, communities, 'graphify-out/wiki') Type guard
def communities_match_graph(communities: dict, G) -> bool:
"""True when at least one community node ID exists in G."""
nodes = set(G.nodes)
return any(n in nodes for members in communities.values() for n in members) Try / catch
try:
to_wiki(G, communities, 'graphify-out/wiki')
except ValueError as e:
if 'stale' in str(e):
raise SystemExit('sidecar and graph are out of sync — full re-extract required') from e
raise Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- communities dict is empty — refusing to clear wiki/. Run `gr
- ERROR: Graph is empty - extraction produced no nodes.
- ERROR: refused to shrink graphify-out/graph.json (existing g
- module {__name__!r} has no attribute {name!r}
- Cannot read graph file {path}: {exc}. Re-run 'graphify extra
AI-assisted analysis of Graphify-Labs/graphify@7fe58b0b0f (2026-08-14).
Data as JSON: /api/errors/00e805d1e65bad6e.
Report an issue: GitHub.