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
- Verify options.basePath exists and is a directory before calling create() (fs.existsSync + fs.statSync().isDirectory()).
- Read the wrapped ${result.error} in the message — it names the SDK-level cause; fix that underlying issue.
- Ensure the native fff library is installed (npx @ff-labs/fff-node download or cargo build --release -p fff-c).
- Check read permissions on basePath and that it is on a mounted, accessible filesystem.
- 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
- Always resolve basePath to an absolute, existing directory before create().
- Surface the inner result.error from the message to diagnose the SDK-level cause.
- Ensure the native binary is installed before picker startup.
- Clear the fff index/DB after plugin upgrades if creation keeps failing.
- Handle scan-timeout semantics: waitForScan bounds startup but does not guarantee a full index.
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
- Failed to init file picker
- File picker not initialized. Call fff_create_instance first.
- fff native library not found. Run `npx @ff-labs/fff-node…
- fff native library not found. Run `npx @ff-labs/fff-node…
- FFF picker factory is not initialized
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)