dmtrKovalenko/fff · error
fff_search_mixed returned null search result
Error message
fff_search_mixed returned null search result
What it means
The FFI envelope from fff_search_mixed reported success, but its result handle pointer is 0 — meaning the native side returned a null search result even though the call 'succeeded'. The binding treats this as a contract violation and returns an error rather than fabricating an empty result.
Solutions
- Ensure the FileFinder instance is alive (not destroyed) when calling mixed search — check handle validity first.
- Rebuild/reinstall the native library to rule out version mismatch with the JS bindings.
- If reproducible on a healthy instance, report it: a success envelope with a null handle is a native-side bug.
Example fix
// before const r = ffiSearchMixed(handle, query); // handle may be stale // after const alive = ensureAlive(handle); if (!alive.ok) return alive; const r = ffiSearchMixed(alive.value, query);
Defensive patterns
Strategy: try-catch
Validate before calling
if (finder === null || !finder.isAlive()) return err('finder destroyed'); Type guard
function isAlive(finder) { return finder != null && finder.handle !== null; } Try / catch
try { const r = await finder.searchMixed(q); } catch (e) { if (e.message.includes('null search result')) { recreateFinder(); } } Prevention
- Guard all FFI calls with an aliveness check.
- Route all native calls through one owner that tracks instance lifetime.
- Upgrade native + bindings together to avoid envelope/handle ABI drift.
When it happens
Trigger: ffiSearchMixed where the native fff_search_mixed produced a success envelope with handlePtr === 0, e.g. native ran with an uninitialized/garbage-collected handle or the native call failed to allocate the result struct.
Common situations: Calling search on a FileFinder whose native instance was already destroyed (double-free / use-after-free scenario); native OOM while allocating the result; a bug in a mismatched native library version.
Related errors
- FFI returned null pointer
- grep returned null result
- scan progress returned null
- fff native library not found. Run `npx @ff-labs/fff-node…
- Instance handle is null. Create one with…
AI-assisted analysis of dmtrKovalenko/fff@7f8537e70f (2026-09-10).
Data as JSON: /api/errors/8b376eb03f7350ff.
Report an issue: GitHub.
Appendix: source
Thrown at packages/fff-bun/src/ffi.ts:908
modificationFrecencyScore: Number(read.i64(pp, MI_MODFR)),
totalFrecencyScore: Number(read.i64(pp, MI_TOTAL_FR)),
},
};
}
/**
* Parse an FffMixedSearchResult from a raw FffResult pointer, then free native memory.
*/
function parseMixedSearchResult(resultPtr: Pointer | null): Result<MixedSearchResult> {
if (resultPtr === null) {
return err("FFI returned null pointer");
}
const envelope = readResultEnvelope(resultPtr);
if (!("success" in envelope)) return envelope;
if (envelope.handlePtr === 0) {
return err("fff_search_mixed returned null search result");
}
const hp = asPtr(envelope.handlePtr);
const count = read.u32(hp, MSR_COUNT);
const totalMatched = read.u32(hp, MSR_MATCHED);
const totalFiles = read.u32(hp, MSR_TOTAL_FILES);
const totalDirs = read.u32(hp, MSR_TOTAL_DIRS);
// Read location
const locTag = read.u8(hp, MSR_LOC_TAG);
let location: Location | undefined;
if (locTag === 1) {
location = { type: "line", line: read.i32(hp, MSR_LOC_LINE) };
} else if (locTag === 2) {
location = {
type: "position",
line: read.i32(hp, MSR_LOC_LINE),
col: read.i32(hp, MSR_LOC_COL),View on GitHub (pinned to 7f8537e70f)