dmtrKovalenko/fff · error · Error

Failed to create FFF file picker for

Error message

Failed to create FFF file picker for ${options.basePath}: ${result.error}

What it means

create() opens an FFF FileFinder via the underlying SDK and requires a successful, scanned picker. When openWithDbFallback returns result.ok === false, the SDK's error string is wrapped in this message and thrown, so callers get a single descriptive failure for picker startup problems (bad base path, native library issues, or scan/DB errors surfaced by the SDK).

Solutions

  1. Verify options.basePath exists and is a directory before calling create() (fs.existsSync + fs.statSync().isDirectory()).
  2. Read the wrapped ${result.error} in the message — it names the SDK-level cause; fix that underlying issue.
  3. Ensure the native fff library is installed (npx @ff-labs/fff-node download or cargo build --release -p fff-c).
  4. Check read permissions on basePath and that it is on a mounted, accessible filesystem.
  5. If the error points at the DB, clear the fff cache/frecency DB so a fresh index is built.

Example fix

// before
const picker = await fff.create({ basePath: cfg.basePath });
// after
import { statSync } from 'fs';
if (!statSync(cfg.basePath, { throwIfNoEntry: false })?.isDirectory()) {
  throw new Error(`basePath is not a directory: ${cfg.basePath}`);
}
const picker = await fff.create({ basePath: cfg.basePath });
Defensive patterns

Strategy: try-catch

Validate before calling

import { statSync } from 'fs';
const st = statSync(basePath, { throwIfNoEntry: false });
if (!st?.isDirectory()) throw new Error(`basePath must be an existing directory: ${basePath}`);

Type guard

function isDirectory(p: string): boolean {
  return statSync(p, { throwIfNoEntry: false })?.isDirectory() ?? false;
}

Try / catch

try {
  const picker = await fff.create({ basePath });
} catch (e) {
  if (String(e.message).startsWith('Failed to create FFF file picker')) {
    console.error('Check basePath exists, is readable, and the native lib is installed:', e.message);
    // optionally clear the fff DB and retry once
  } else throw e;
}

Prevention

When it happens

Trigger: Calling create({ basePath, ... }) where basePath does not exist or is not a directory, the native fff library cannot load, the SDK result envelope carries an error (e.g. index/DB corruption or permission failure on the base path), or the FFI create call returns { ok: false, error }.

Common situations: Typos or relative paths in basePath config, pointing at a deleted/unmounted directory, running without read access to the target folder, or a stale/corrupt frecency DB that even the fallback path cannot recover.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of dmtrKovalenko/fff@7f8537e70f (2026-09-10). Data as JSON: /api/errors/abb6d475f7ba4af9. Report an issue: GitHub.

Appendix: source

Thrown at packages/pi-fff/src/file-picker.ts:40

    onDbFailure?: (error: string) => void;
  }) {
    this.frecencyDbPath = opts.frecencyDbPath;
    this.historyDbPath = opts.historyDbPath;
    this.onDbFailure = opts.onDbFailure;
  }

  /** True once the databases were given up on, so pickers open without them. */
  get databasesDisabled(): boolean {
    return this.dbDisabled;
  }

  /** Opens a scanned, ready-to-use picker. Throws if it cannot be created. */
  async create(options: PickerOptions): Promise<FileFinderApi> {
    const { FileFinder } = await loadSdk();
    const result = this.openWithDbFallback(FileFinder, options);

    if (!result.ok) {
      throw new Error(
        `Failed to create FFF file picker for ${options.basePath}: ${result.error}`,
      );
    }

    // waitForScan() also resolves on timeout, so this bounds startup rather
    // than guaranteeing a complete index.
    await result.value.waitForScan(SCAN_TIMEOUT_MS);
    return result.value;
  }

  private openWithDbFallback(
    FileFinder: FileFinderStatic,
    options: PickerOptions,
  ): Result<FileFinderApi> {
    const init: InitOptions = { ...options, aiMode: true };
    if (this.dbDisabled) return FileFinder.create(init);

    const result = FileFinder.create({

View on GitHub (pinned to 7f8537e70f)