stamparm/maltrail · error · ConfigError

invalid configuration value for 'CAPTURE_FANOUT_MODE

Error message

invalid configuration value for 'CAPTURE_FANOUT_MODE' ('{v}')

What it means

CAPTURE_FANOUT_MODE selects how captured packets are distributed across processing threads and is parsed with FanoutMode::parse. If the configured string is not a recognized mode name, the loader bails with this message.

Solutions

  1. Set CAPTURE_FANOUT_MODE to a supported mode name — check FanoutMode::parse in the sensor source/docs for the exact accepted strings (e.g. hash/flow-based modes).
  2. Fix casing/spelling to match the enum variant names exactly.
  3. Remove the option to use the default fanout mode.
  4. If migrating from another sensor version, map the old mode name to the current set.

Example fix

// before (config.conf)
CAPTURE_FANOUT_MODE=round-robin

// after (config.conf)
CAPTURE_FANOUT_MODE=hash
Defensive patterns

Strategy: validation

Validate before calling

let v = get_str(&raw, "CAPTURE_FANOUT_MODE");
if !v.is_empty() && FanoutMode::parse(&v).is_none() {
    eprintln!("CAPTURE_FANOUT_MODE '{v}' is not a recognized mode");
}

Prevention

When it happens

Trigger: Setting CAPTURE_FANOUT_MODE to an unregistered mode string (e.g. 'round-robin', 'rr', 'random') that FanoutMode::parse does not recognize; special values may be handled inline, but everything else must match an enum variant name.

Common situations: Admins inventing mode names based on other capture tools' terminology; typos in a valid mode name (wrong case or spelling); configs copied from forks/versions with different mode names.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of stamparm/maltrail@77cfb06d76 (2026-09-13). Data as JSON: /api/errors/162de287454343aa. Report an issue: GitHub.

Appendix: source

Thrown at sensor/src/config.rs:966

        };

        let capture_fanout_mode = {
            let v = get_str(&raw, "CAPTURE_FANOUT_MODE");
            if v.trim().is_empty() {
                // Unset. A single worker never forms a fanout group, so the mode is moot there.
                // Above one it decides whether the scan heuristics survive being split at all -
                // flow hashing costs 34% of them at 8 workers - so the default is the mode that
                // does not quietly trade detections for throughput. An operator who wants the old
                // behaviour asks for it by name.
                if capture_workers > 1 {
                    FanoutMode::Source
                } else {
                    FanoutMode::Hash
                }
            } else {
                match FanoutMode::parse(&v) {
                    Some(m) => m,
                    None => bail!("invalid configuration value for 'CAPTURE_FANOUT_MODE' ('{v}')"),
                }
            }
        };

        let offline_timestamps = {
            let v = get_str(&raw, "OFFLINE_TIMESTAMPS").to_ascii_lowercase();
            match v.trim() {
                "" | "pcap" => TimestampSource::Pcap,
                "wallclock" | "wall-clock" | "now" => TimestampSource::Wallclock,
                other => bail!("invalid configuration value for 'OFFLINE_TIMESTAMPS' ('{other}')"),
            }
        };

        let sensor_name = {
            let v = get_str(&raw, "SENSOR_NAME");
            if v.is_empty() {
                hostname()
            } else {

View on GitHub (pinned to 77cfb06d76)