Graphify-Labs/graphify · error · FileNotFoundError
graph.json not found: {resolved_path}
Error message
graph.json not found: {resolved_path} What it means
Raised by _GraphContextManager.load (graphify/serve.py) when Path(resolved_path).stat() raises FileNotFoundError while constructing the (mtime_ns, size) cache key. The message re-raises with `from None` for a clean chain, since the stat failure already tells the whole story: there is no graph.json at the resolved location. This is the concurrency-safe variant of the missing-file check — it catches the file disappearing between request and stat.
Source
Thrown at graphify/serve.py:146
"G": graph,
"communities": communities,
}
return entry
def load(self, resolved_path: str, *, pinned: bool = False) -> tuple[nx.Graph, dict[int, list[str]]]:
"""Return a fresh context, retaining project contexts by LRU order.
``resolved_path`` is resolved by the caller, making this method the
sole owner of file statting and cache-key construction.
``pinned=True`` is reserved for the server's configured default graph;
it remains warm without consuming a project-cache slot.
"""
with self._lock:
try:
stat_result = Path(resolved_path).stat()
except FileNotFoundError:
raise FileNotFoundError(f"graph.json not found: {resolved_path}") from None
key = (stat_result.st_mtime_ns, stat_result.st_size)
entries = self._pinned if pinned else self._entries
entry = entries.get(resolved_path)
if entry is not None and entry["key"] == key:
if not pinned:
self._entries.move_to_end(resolved_path)
return entry["G"], entry["communities"]
entry = self._load_entry(resolved_path, key)
entries[resolved_path] = entry
if not pinned:
self._entries.move_to_end(resolved_path)
while len(self._entries) > self._max_contexts:
self._entries.popitem(last=False)
return entry["G"], entry["communities"]
def _strip_diacritics(text: str | None) -> str:View on GitHub (pinned to 7fe58b0b0f)
Solutions
- Run the graph build in the target project so graphify-out/graph.json exists, then retry the tool call.
- Correct the project_path sent by the MCP client to the checkout that actually contains the graph.
- Guard concurrent rebuilds: build to a temp dir and atomically rename so readers never observe a missing graph.json.
- In long-lived servers, re-check existence on this error rather than keeping the dead path cached.
Example fix
# before
G, comms = ctx.load(str(project / "graphify-out" / "graph.json"))
# after
graph_json = project / "graphify-out" / "graph.json"
if not graph_json.exists():
raise ToolError(f"No graph at {graph_json}; run /graphify in {project} first")
G, comms = ctx.load(str(graph_json)) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def stat_graph(resolved_path: str) -> tuple[int, int] | None:
try:
st = Path(resolved_path).stat()
return (st.st_mtime_ns, st.st_size)
except FileNotFoundError:
return None
if stat_graph(resolved_path) is None:
raise ToolError(f"no graph.json at {resolved_path}; run /graphify first") Type guard
def graph_present(resolved_path: str) -> bool:
return Path(resolved_path).exists() Try / catch
try:
G, comms = ctx.load(resolved_path)
except FileNotFoundError as e:
if "graph.json not found" in str(e):
return tool_error("graph not built for this project; ask the user to run /graphify")
raise Prevention
- Stat the graph.json path before each session that will query it.
- Make rebuilds atomic (build to temp, rename) so stat never observes a gap during hot-reload.
- Drop dead project paths from client configs after moving checkouts.
When it happens
Trigger: Calling ctx.load(resolved_path) on an MCP tool request whose project_path resolves to a checkout without graphify-out/graph.json, or where the file was deleted by a concurrent rebuild/clean between a prior successful load and this one.
Common situations: MCP client points at a project that has never run /graphify; git clean or CI wipe removing graphify-out mid-session; hot-reload racing a destructive rebuild; stale IDE MCP config after the repo moved.
Related errors
- Graph file not found: {resolved}
- Graph file not found: {resolved}
- could not load graph.json at {resolved_path}
- file_hash requires a file, got: {p}
- graphify output not found: {paths['graph']}. Run graphify fi
AI-assisted analysis of Graphify-Labs/graphify@7fe58b0b0f (2026-08-14).
Data as JSON: /api/errors/79ece0e22db77f49.
Report an issue: GitHub.