Graphify-Labs/graphify · error · IsADirectoryError

file_hash requires a file, got: {p}

Error message

file_hash requires a file, got: {p}

What it means

A preflight existence check in the /graphify query skill (tools/skillgen/expected/graphify__skills__agents__references__query.md:18). Before any BFS/DFS traversal, the skill runs a tiny Python snippet that raises SystemExit(1) with this message when graphify-out/graph.json is missing. It tells the agent/user that the knowledge graph must be built by /graphify <path> before queries can run.

Source

Thrown at graphify/cache.py:430

    Uses a stat-based fastpath (size + mtime_ns) to skip full reads when the
    file hasn't changed. Falls through to full SHA256 on first encounter, when
    stat changes, and when the recorded signature is not yet provably stable
    (see :func:`_stat_sig_fresh`) — so two different contents can never share a
    digest. Index is flushed atomically at process exit.

    Using a relative path (not absolute) makes cache entries portable across
    machines and checkout directories, so shared caches and CI work correctly.
    Falls back to the resolved absolute path if the file is outside root.

    For Markdown files (.md), only the body below the YAML frontmatter is hashed,
    so metadata-only changes (e.g. reviewed, status, tags) do not invalidate the cache.
    """
    global _stat_index_dirty
    p = _normalize_path(Path(path))
    root = _normalize_path(Path(root))
    if not p.is_file():
        raise IsADirectoryError(f"file_hash requires a file, got: {p}")

    # The stat index is a cache artifact, so it must follow the cache location
    # (cache_root), not the key-anchor root — otherwise it leaves a stray
    # graphify-out/cache/stat-index.json inside the analyzed source tree even when
    # the AST cache itself is redirected to CWD (#1774 completion).
    _ensure_stat_index(root, cache_root=cache_root)
    resolved = p.resolve()
    abs_key = str(resolved)
    # The salt is the path component that enters the digest (relative to root, or
    # the absolute-path fallback). The stat-index memo MUST be keyed by it too:
    # the same file hashed under two different roots yields two different digests
    # (this happens within one `--out` run), and a memo keyed only by absolute
    # path served whichever was computed first — making file_hash order-dependent
    # and poisoning the persisted stat-index across runs (#1989). Store one digest
    # per salt so alternating roots don't force re-reads.
    try:
        salt = resolved.relative_to(Path(root).resolve()).as_posix().lower()
    except ValueError:

View on GitHub (pinned to 7fe58b0b0f)

Solutions

  1. Run /graphify <path> on the codebase first to build graphify-out/graph.json, then retry the query.
  2. Confirm you are in the same working directory where the graph was built (the check uses the relative path graphify-out/graph.json).
  3. If a previous build failed early (empty extraction or shrink refusal), fix that failure first — it never produced a graph.json.
  4. If graph.json exists under a different root, either cd to that root or copy/merge the graphify-out directory.

Example fix

# before: query without a graph
/graphify query "how does auth work?"
# ERROR: No graph found ...

# after: build, then query
/graphify .
/graphify query "how does auth work?"
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

if not Path('graphify-out/graph.json').exists():
    print('No graph yet - run the build step before querying; skipping query flow.')
else:
    print('graph present - safe to run Step 0 vocabulary extraction and traversal')

Prevention

When it happens

Trigger: Invoking /graphify query (or ask/path/explain) in a workspace where graphify-out/graph.json does not exist — the graph was never built, was built in a different directory, or graphify-out/ was deleted/cleaned.

Common situations: Fresh clone or fresh workspace where /graphify was never run; running the query command from the wrong working directory (graph.json lives elsewhere); git clean or CI artifact cleanup removing graphify-out/; a failed earlier build that exited before writing graph.json (e.g. the empty-graph guard fired).

Related errors


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