epi052/feroxbuster · error

Could not get underlying wordlist

Error message

Could not get underlying wordlist

What it means

get_wordlist bails when the cached wordlist behind the internal lock cannot be retrieved. Both update_all_bar_lengths and ordered_scan_url depend on it; without the wordlist, progress bars and scan ordering cannot be computed.

Solutions

  1. Verify the wordlist file loaded successfully at startup (fix path/permissions reported by earlier errors)
  2. Call get_wordlist only after wordlist initialization completes
  3. Recover from a poisoned lock by identifying and fixing the earlier panicking task
  4. In tests, load a wordlist (or a small test list) before invoking scan setup

Example fix

// before
let wordlist = scan_container.get_wordlist().await?; // wordlist never loaded
// after
scan_container.initialize_wordlist("/usr/share/wordlists/common.txt").await?;
let wordlist = scan_container.get_wordlist().await?;
Defensive patterns

Strategy: try-catch

Validate before calling

if !Path::new(&config.wordlist).exists() {
    return Err(format!("wordlist not found: {}", config.wordlist));
}

Try / catch

match scan_container.get_wordlist().await {
    Ok(list) => list,
    Err(e) if e.to_string().contains("Could not get underlying wordlist") => {
        log::error!("wordlist not loaded; check earlier load errors");
        return Err(e);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling get_wordlist when the wordlist slot is None (wordlist not loaded) or its lock guard cannot be acquired — e.g. after the wordlist task failed to load the file or a panic poisoned the lock.

Common situations: The configured wordlist file failed to load earlier (bad path, permission) so the cache was never populated; accessing wordlist during shutdown; tests instantiating the scanner container without loading a wordlist.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of epi052/feroxbuster@1f595dab5c (2026-09-13). Data as JSON: /api/errors/7255b0e2f70cb2e4. Report an issue: GitHub.

Appendix: source

Thrown at src/event_handlers/scans.rs:326

        }

        log::trace!("exit: update_all_bar_lengths");
        Ok(())
    }

    /// Helper to easily get the (locked) underlying wordlist
    pub fn get_wordlist(&self, offset: usize) -> Result<Arc<Vec<String>>> {
        if let Ok(guard) = self.wordlist.lock().as_ref() {
            if let Some(list) = guard.as_ref() {
                return if offset > 0 {
                    Ok(Arc::new(list[offset..].to_vec()))
                } else {
                    Ok(list.clone())
                };
            }
        }

        bail!("Could not get underlying wordlist")
    }

    /// wrapper around scanning a url to stay DRY
    async fn ordered_scan_url(&mut self, targets: Vec<String>, order: ScanOrder) -> Result<()> {
        log::trace!("enter: ordered_scan_url({targets:?}, {order:?})");
        let should_test_deny = !self.handles.config.url_denylist.is_empty()
            || !self.handles.config.regex_denylist.is_empty();

        for target in targets {
            if self.data.contains(&target) && matches!(order, ScanOrder::Latest) {
                // FeroxScans knows about this url and scan isn't an Initial scan
                // initial scans are skipped because when resuming from a .state file, the scans
                // will already be populated in FeroxScans, so we need to not skip kicking off
                // their scans
                continue;
            }

            let scan = if let Some(ferox_scan) = self.data.get_scan_by_url(&target) {

View on GitHub (pinned to 1f595dab5c)