dmtrKovalenko/fff · error

Failed to acquire file picker lock

Error message

Failed to acquire file picker lock: {}

What it means

fff_search takes a read lock on the instance's RwLock-protected FilePicker; if the underlying lock primitive returns Err (a poisoned lock, i.e. a writer panicked while holding it), the FFI layer converts that into this error rather than propagating the panic.

Solutions

  1. Find and fix the panic in the thread that poisoned the lock (check logs from the watcher/index threads).
  2. Recreate the instance: destroy the poisoned one with fff_destroy_instance and call fff_create_instance again.
  3. Restart the host process if instance recreation is not feasible.
  4. Report the underlying panic to the library maintainers if it reproduces — lock poisoning here indicates an internal bug.

Example fix

null
Defensive patterns

Strategy: retry

Try / catch

local res = fff.search(inst, q)
if res.is_err and res.message:find('lock') then
  recreate_instance_and_retry()
end

Prevention

When it happens

Trigger: Calling fff_search (or any picker access) on an instance whose picker RwLock was poisoned by a panic in another thread — typically a background watcher or a previous FFI call that panicked while holding the write lock.

Common situations: A previous index operation panicked (bug in a watcher callback) leaving the lock poisoned; multi-threaded embedding where one thread crashed mid-update; using an instance handle after a failed background operation.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at crates/fff-c/src/lib.rs:363

) -> *mut FffResult {
    let inst = match unsafe { instance_ref(fff_handle) } {
        Ok(i) => i,
        Err(e) => return e,
    };

    let query_str = match unsafe { cstr_to_str(query) } {
        Some(s) => s,
        None => return FffResult::err("Query is null or invalid UTF-8"),
    };

    let current_file_str = unsafe { optional_cstr(current_file) };
    let page_size = default_u32(page_size, 100) as usize;
    let min_combo_count = default_u32(min_combo_count, 3);
    let combo_boost_multiplier = default_i32(combo_boost_multiplier, 100);

    let picker_guard = match inst.picker.read() {
        Ok(g) => g,
        Err(e) => return FffResult::err(&format!("Failed to acquire file picker lock: {}", e)),
    };

    let picker = match picker_guard.as_ref() {
        Some(p) => p,
        None => {
            return FffResult::err("File picker not initialized. Call fff_create_instance first.");
        }
    };

    // Get query tracker ref for combo matching
    let qt_guard = match inst.query_tracker.read() {
        Ok(q) => q,
        Err(_) => return FffResult::err("Failed to acquire query tracker lock"),
    };
    let query_tracker_ref = qt_guard.as_ref();

    let parser = QueryParser::default();
    let parsed = parser.parse(query_str);

View on GitHub (pinned to 7f8537e70f)