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

  1. Update the fff-node package and rebuild/download the matching native binary so TS bindings and Rust library versions align.
  2. Verify the FileFinder instance is still alive (not destroyed) before searching and that scanning has completed.
  3. Reproduce with a minimal query; if it persists, file a bug with the native library version and query.
  4. 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

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


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)