Summary
During graphify extract, the per-chunk incremental semantic cache checkpoint fails for every chunk that contains an oversized (sliced) document, printing:
[graphify] incremental cache checkpoint failed: argument should be a str or an os.PathLike object where __fspath__ returns a str, not 'FileSlice'
Extraction completes and produces a valid graph — but the incremental cache the checkpoint exists to provide is silently defeated for those chunks, so a re-run (or a run resumed after a crash/kill/rate-limit) re-bills them instead of reusing cached results.
Environment
- graphify (graphifyy) 0.9.14, Python 3.13, macOS.
- Observed on
graphify extract . --backend claude-cli over a 70-document corpus (5 chunks): chunks 1–4 each printed the failure; chunk 5 (no sliced doc) did not.
Root cause
llm.py, _checkpoint_chunk builds the allowed_source_files list as:
# A FileSlice reports its file via `.rel`; a bare Path is the relative source_file itself.
allowed = [getattr(item, "rel", None) or item for item in chunk]
But FileSlice (file_slice.py) is a @dataclass(frozen=True) whose path field is .path — it has no .rel attribute ([a for a in dir(FileSlice) if not a.startswith('__')] is empty of rel). So for every FileSlice, getattr(item, "rel", None) returns None, and or item leaks the FileSlice object itself into allowed.
save_semantic_cache(..., allowed_source_files=allowed) then does, in resolved_source_path:
path = Path(value) # value is a FileSlice -> TypeError
(cache.py), which raises argument should be a str or an os.PathLike object ... not 'FileSlice'. The except Exception in _checkpoint_chunk catches it and prints the best-effort warning, so extraction continues but the chunk is never checkpointed.
The comment at the call site referencing .rel is stale relative to the FileSlice dataclass.
Reproducer
graphify extract . --backend <any> --out <dir> on a corpus containing at least one document large enough to be split into FileSlice units (#1369). Every chunk that includes a slice prints the checkpoint failure.
Suggested fix
Resolve a FileSlice's source path via its actual attribute (.path) rather than the non-existent .rel — e.g. getattr(item, "path", None) or item, or unwrap FileSlice explicitly before building allowed. Whatever attribute genuinely carries the relative source_file should be used; .rel does not exist on the current dataclass.
Summary
During
graphify extract, the per-chunk incremental semantic cache checkpoint fails for every chunk that contains an oversized (sliced) document, printing:Extraction completes and produces a valid graph — but the incremental cache the checkpoint exists to provide is silently defeated for those chunks, so a re-run (or a run resumed after a crash/kill/rate-limit) re-bills them instead of reusing cached results.
Environment
graphify extract . --backend claude-cliover a 70-document corpus (5 chunks): chunks 1–4 each printed the failure; chunk 5 (no sliced doc) did not.Root cause
llm.py,_checkpoint_chunkbuilds theallowed_source_fileslist as:But
FileSlice(file_slice.py) is a@dataclass(frozen=True)whose path field is.path— it has no.relattribute ([a for a in dir(FileSlice) if not a.startswith('__')]is empty ofrel). So for everyFileSlice,getattr(item, "rel", None)returnsNone, andor itemleaks theFileSliceobject itself intoallowed.save_semantic_cache(..., allowed_source_files=allowed)then does, inresolved_source_path:(
cache.py), which raisesargument should be a str or an os.PathLike object ... not 'FileSlice'. Theexcept Exceptionin_checkpoint_chunkcatches it and prints the best-effort warning, so extraction continues but the chunk is never checkpointed.The comment at the call site referencing
.relis stale relative to theFileSlicedataclass.Reproducer
graphify extract . --backend <any> --out <dir>on a corpus containing at least one document large enough to be split intoFileSliceunits (#1369). Every chunk that includes a slice prints the checkpoint failure.Suggested fix
Resolve a
FileSlice's source path via its actual attribute (.path) rather than the non-existent.rel— e.g.getattr(item, "path", None) or item, or unwrapFileSliceexplicitly before buildingallowed. Whatever attribute genuinely carries the relative source_file should be used;.reldoes not exist on the current dataclass.