dmtrKovalenko/fff · error
fff_search_directories returned null search result
Error message
fff_search_directories returned null search result
What it means
fff_search_directories returned a null handle pointer inside the FffResult envelope, meaning the native library signaled success but produced no FffDirSearchResult. The Node FFI layer treats this as an internal invariant violation because a successful directory search must always yield a result struct. This usually indicates a bug or race in the Rust side rather than a user error.
Solutions
- Update the fff-node package and rebuild/download the matching native binary so TS bindings and Rust library versions align.
- Verify the FileFinder instance is still alive (not destroyed) before searching and that scanning has completed.
- Reproduce with a minimal query; if it persists, file a bug with the native library version and query.
- Wrap calls in Result handling and retry the search once — transient races during index rebuild may resolve.
Example fix
// before
const res = finder.searchDirectories({ query: 'src' });
if (!res.ok) throw new Error(res.error);
// after
const res = finder.searchDirectories({ query: 'src' });
if (!res.ok) {
if (res.error.includes('null search result')) {
await finder.rescan(); // rebuild native state, then retry
return finder.searchDirectories({ query: 'src' });
}
throw new Error(res.error);
} Defensive patterns
Strategy: fallback
Validate before calling
// no pre-call check possible; verify environment instead const binaryOk = typeof ffiSearchDirectories === 'function' && nativeLibVersion() === expectedVersion;
Type guard
function hasSearchHandle(finder: FileFinder): finder is FileFinder & { handle: NativeHandle } {
return finder.isAlive();
} Try / catch
const res = finder.searchDirectories({ query });
if (!res.ok) {
if (res.error.includes('null search result')) {
await finder.rescan();
return finder.searchDirectories({ query }); // one retry
}
throw new Error(res.error);
} Prevention
- Keep the native binary and fff-node bindings on matching versions.
- Recreate the finder rather than reusing it after teardown/rescan cycles.
- Log native library version at startup to correlate bugs.
- Handle Result errors explicitly instead of assuming success implies a struct.
When it happens
Trigger: Calling FileFinder.searchDirectories (via ffiSearchDirectories) when the native fff_search_directories call returns success but a null handle in the envelope — e.g. native code failed to allocate the result struct or a race during shutdown/index teardown.
Common situations: Running against a stale or mismatched prebuilt .so/.dll that does not match the TS FFI bindings; searching after the picker's index was torn down; a native bug when the scanned directory set is empty or the handle was already freed.
Related errors
- fff_search_mixed returned null search result
- Instance handle is null. Create one with…
- opts is null
- Query is null or invalid UTF-8
- File picker not initialized. Call fff_create_instance first.
AI-assisted analysis of dmtrKovalenko/fff@7f8537e70f (2026-09-10).
Data as JSON: /api/errors/77727573e7445585.
Report an issue: GitHub.
Appendix: source
Thrown at packages/fff-node/src/ffi.ts:1049
const [envelope] = restorePointer({
retType: [FFF_RESULT_STRUCT],
paramsValue: wrapPointer([rawPtr]),
}) as unknown as [FffResultRaw];
const success = envelope.success !== 0;
if (!success) {
const errorMsg = readCString(envelope.error) || "Unknown error";
freeResult(rawPtr);
return err(errorMsg);
}
const handlePtr = envelope.handle;
// Free the FffResult envelope (does NOT free handle)
freeResult(rawPtr);
if (isNullPointer(handlePtr)) {
return err("fff_search_directories returned null search result");
}
// Read FffDirSearchResult struct
const [sr] = restorePointer({
retType: [FFF_DIR_SEARCH_RESULT_STRUCT],
paramsValue: wrapPointer([handlePtr]),
}) as unknown as [FffDirSearchResultRaw];
const count = sr.count;
// Read items and scores via accessor functions
const items: DirItem[] = [];
const scores: Score[] = [];
for (let i = 0; i < count; i++) {
const rawItem = callAccessor<FffDirItemRaw>(
"fff_dir_search_result_get_item",
handlePtr,View on GitHub (pinned to 7f8537e70f)