epi052/feroxbuster · error

Could not get underlying FeroxScans

Error message

Could not get underlying FeroxScans

What it means

ferox_scans returns this error when the FeroxScans handle behind the container's RwLock cannot be read or is None. Callers use this to get scan data (e.g. collected_extensions); without the handle, scan bookkeeping is unavailable.

Solutions

  1. Initialize FeroxScans on the container before querying it
  2. Recover or replace a poisoned lock (check for an earlier panic that poisoned scans)
  3. Call ferox_scans only after the scan event loop has started
  4. In tests, use the standard container constructor instead of a partial default

Example fix

// before
let scans = container.ferox_scans()?; // before init
// after
container.initialize()?;
let scans = container.ferox_scans()?;
Defensive patterns

Strategy: try-catch

Validate before calling

if container.scans_initialized() {
    let scans = container.ferox_scans()?;
}

Try / catch

let scans = match container.ferox_scans() {
    Ok(s) => s,
    Err(e) if e.to_string().contains("Could not get underlying FeroxScans") => {
        log::warn!("FeroxScans not initialized yet");
        return Ok(());
    }
    Err(e) => return Err(e),
};

Prevention

When it happens

Trigger: Calling ferox_scans when self.scans holds None (container created without FeroxScans initialized) or the RwLock read fails due to poisoning after a panic elsewhere.

Common situations: Accessing scan metadata before the scan handler initialized FeroxScans; use in tests with a manually-built container; a poisoned lock after a panic in a scan task.

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 epi052/feroxbuster@1f595dab5c (2026-09-13). Data as JSON: /api/errors/bc1a8a8212f9b854. Report an issue: GitHub.

Appendix: source

Thrown at src/event_handlers/container.rs:181

        let methods = self.config.methods.len().max(1);
        let base_requests = 1; // the bare word (with optional slash)
        let static_extensions = self.config.extensions.len();
        let dynamic_extensions = self.num_collected_extensions();

        let total_paths = base_requests + static_extensions + dynamic_extensions;

        total_paths * methods
    }

    /// Helper to easily get the (locked) underlying FeroxScans object
    pub fn ferox_scans(&self) -> Result<Arc<FeroxScans>> {
        if let Ok(guard) = self.scans.read().as_ref() {
            if let Some(handle) = guard.as_ref() {
                return Ok(handle.data.clone());
            }
        }

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

View on GitHub (pinned to 1f595dab5c)