dmtrKovalenko/fff · error

Failed to acquire query tracker lock

Error message

Failed to acquire query tracker lock: {}

What it means

Analogous to the frecency case: QueryTracker::open succeeded but installing the tracker into the shared query-tracker slot via init() failed while acquiring its lock. The underlying lock error is embedded. Creation aborts since query history cannot be maintained.

Solutions

  1. Create instances sequentially or guard creation with an app-level mutex.
  2. Retry once; treat repeated lock errors (poisoned lock) as requiring process restart.
  3. Avoid multiple components in the same process initializing the shared query tracker independently.
  4. Investigate earlier panics in logs that may have poisoned the lock.

Example fix

// before
[createWithHistory(a), createWithHistory(b)].forEach(Promise.all);
// after
createWithHistory(a); createWithHistory(b); // one at a time
Defensive patterns

Strategy: retry

Try / catch

try {
  createInstanceWithHistory(opts);
} catch (e) {
  if (/Failed to acquire query tracker lock/.test(e.message)) {
    await delay(50);
    return createInstanceWithHistory(opts);
  }
  throw e;
}

Prevention

When it happens

Trigger: Concurrent fff_create_instance* calls racing on the shared query tracker; poisoned mutex from an earlier panic during query tracker init.

Common situations: Parallel instance creation at app startup; a panic in another thread earlier in the process poisoning the RwLock/Mutex; multiple bindings (Lua + Node) initializing in one host process.

Related errors


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

Appendix: source

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

        match FrecencyTracker::open(frecency_path) {
            Ok(tracker) => {
                if let Err(e) = shared_frecency.init(tracker) {
                    return FffResult::err(&format!("Failed to acquire frecency lock: {}", e));
                }
            }
            Err(e) => return FffResult::err(&format!("Failed to init frecency db: {}", e)),
        }
    }

    if let Some(ref history_path) = history_path {
        if let Some(parent) = PathBuf::from(history_path).parent() {
            let _ = std::fs::create_dir_all(parent);
        }

        match QueryTracker::open(history_path) {
            Ok(tracker) => {
                if let Err(e) = query_tracker.init(tracker) {
                    return FffResult::err(&format!("Failed to acquire query tracker lock: {}", e));
                }
            }
            Err(e) => return FffResult::err(&format!("Failed to init query tracker db: {}", e)),
        }
    }

    let mode = if opts.ai_mode {
        FFFMode::Ai
    } else {
        FFFMode::Neovim
    };

    let cache_budget = fff::ContentCacheBudget::from_overrides(
        opts.cache_budget_max_files as usize,
        opts.cache_budget_max_bytes,
        opts.cache_budget_max_file_size,
    );

View on GitHub (pinned to 7f8537e70f)