{"record":{"id":"1d6a3ac3cfef62fd","repo":"dmtrKovalenko/fff","slug":"failed-to-acquire-file-picker-lock","errorCode":null,"errorMessage":"Failed to acquire file picker lock: {}","messagePattern":"Failed to acquire file picker lock: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/fff-c/src/lib.rs","lineNumber":363,"sourceCode":") -> *mut FffResult {\n    let inst = match unsafe { instance_ref(fff_handle) } {\n        Ok(i) => i,\n        Err(e) => return e,\n    };\n\n    let query_str = match unsafe { cstr_to_str(query) } {\n        Some(s) => s,\n        None => return FffResult::err(\"Query is null or invalid UTF-8\"),\n    };\n\n    let current_file_str = unsafe { optional_cstr(current_file) };\n    let page_size = default_u32(page_size, 100) as usize;\n    let min_combo_count = default_u32(min_combo_count, 3);\n    let combo_boost_multiplier = default_i32(combo_boost_multiplier, 100);\n\n    let picker_guard = match inst.picker.read() {\n        Ok(g) => g,\n        Err(e) => return FffResult::err(&format!(\"Failed to acquire file picker lock: {}\", e)),\n    };\n\n    let picker = match picker_guard.as_ref() {\n        Some(p) => p,\n        None => {\n            return FffResult::err(\"File picker not initialized. Call fff_create_instance first.\");\n        }\n    };\n\n    // Get query tracker ref for combo matching\n    let qt_guard = match inst.query_tracker.read() {\n        Ok(q) => q,\n        Err(_) => return FffResult::err(\"Failed to acquire query tracker lock\"),\n    };\n    let query_tracker_ref = qt_guard.as_ref();\n\n    let parser = QueryParser::default();\n    let parsed = parser.parse(query_str);","sourceCodeStart":345,"sourceCodeEnd":381,"githubUrl":"https://github.com/dmtrKovalenko/fff/blob/7f8537e70f0ea1210f9acbbfc4640141105cdc78/crates/fff-c/src/lib.rs#L345-L381","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Find and fix the panic in the thread that poisoned the lock (check logs from the watcher/index threads).","Recreate the instance: destroy the poisoned one with fff_destroy_instance and call fff_create_instance again.","Restart the host process if instance recreation is not feasible.","Report the underlying panic to the library maintainers if it reproduces — lock poisoning here indicates an internal bug."],"exampleFix":"null","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"local res = fff.search(inst, q)\nif res.is_err and res.message:find('lock') then\n  recreate_instance_and_retry()\nend","preventionTips":["Avoid panicking inside callbacks that run while holding picker locks.","Recreate instances after any observed panic in watcher threads.","Report reproducible panics upstream — poisoning signals an internal bug."],"tags":["ffi","concurrency","lock-poisoned","rust"],"backgroundTag":"internal-invariant-violation","analyzedSha":"7f8537e70f0ea1210f9acbbfc4640141105cdc78","analyzedAt":"2026-09-10T07:26:53.407Z","contentChangedAt":"2026-09-10T07:26:53.407Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}