epi052/feroxbuster · error

Could not find FeroxScan associated with

Error message

Could not find FeroxScan associated with {}; this shouldn't happen... exiting

What it means

FeroxScanner::scan_url looks up the FeroxScan record tracked for self.target_url in the central scan collection before starting work. If the record is missing - which the code comments say should never happen because scan_url is only called after the FeroxScan was inserted - it bails with this message and exits, since proceeding without the tracked scan would break progress reporting and limits.

Solutions

  1. Re-run the scan; this is usually a transient/race condition
  2. Ensure scan URLs originate from normal feroxbuster flow (not manual injection into the scan map)
  3. Capture with RUST_BACKTRACE=1 and -vv logging and report upstream if reproducible
Defensive patterns

Strategy: retry

Try / catch

// This is an internal invariant breach; treat as fatal, retry the whole scan
match scanner.scan_url(&url, &handles).await {
    Err(e) if e.to_string().contains("this shouldn't happen") => {
        log::error!("invariant violation: {e}; restarting scan");
    }
    Err(e) => log::warn!("scan error: {e}"),
    Ok(_) => {}
}

Prevention

When it happens

Trigger: scan_url is invoked (via ordered_scan_url or get_scan_by_url) for a URL whose FeroxScan was never inserted into, or was removed from, the SCANS collection.

Common situations: Race conditions where a scan entry is dropped between insertion and lookup, programmatically calling scan APIs for a URL never registered, or internal bugs during scan lifecycle management.

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/db3c25f1779044ff. Report an issue: GitHub.

Appendix: source

Thrown at src/scanner/ferox_scanner.rs:246

            let mut extractor = ExtractorBuilder::default()
                .target(ExtractionTarget::RobotsTxt)
                .url(&self.target_url)
                .handles(self.handles.clone())
                .build()?;
            if let Ok(result) = extractor.extract().await {
                extraction_tasks.push(extractor.request_links(result).await?)
            }
        }

        let scanned_urls = self.handles.ferox_scans()?;
        let ferox_scan = match scanned_urls.get_scan_by_url(&self.target_url) {
            Some(scan) => scan,
            None => {
                let msg = format!(
                    "Could not find FeroxScan associated with {}; this shouldn't happen... exiting",
                    self.target_url
                );
                bail!(fmt_err(&msg))
            }
        };

        let progress_bar = ferox_scan.progress_bar();

        // When acquire is called and the semaphore has remaining permits, the function immediately
        // returns a permit. However, if no remaining permits are available, acquire (asynchronously)
        // waits until an outstanding permit is dropped, at which point, the freed permit is assigned
        // to the caller.
        ferox_scan.set_status(ScanStatus::Waiting)?;
        let _permit = self.scan_limiter.acquire().await;
        ferox_scan.set_status(ScanStatus::Running)?;
        ferox_scan.set_start_time(Instant::now())?;

        if self.handles.config.scan_limit > 0 {
            scan_timer = Instant::now();
            progress_bar.reset();
        }

View on GitHub (pinned to 1f595dab5c)