{"record":{"id":"67de444b11709cd8","repo":"stamparm/maltrail","slug":"missing-mandatory-option-option-in-configuration-file","errorCode":null,"errorMessage":"missing mandatory option '{option}' in configuration file '{}'","messagePattern":"missing mandatory option '(.+?)' in configuration file '(.+?)'","errorType":"validation","errorClass":"ConfigError","httpStatus":null,"severity":"error","filePath":"sensor/src/config.rs","lineNumber":745,"sourceCode":"        _ => false,\n    }\n}\n\nimpl Config {\n    pub fn load(config_file: &Path) -> Result<Config, ConfigError> {\n        if !config_file.is_file() {\n            bail!(\"missing configuration file '{}'\", config_file.display());\n        }\n        crate::cprintln!(\"[i] using configuration file '{}'\", config_file.display());\n        let content = std::fs::read_to_string(config_file)\n            .map_err(|e| ConfigError(format!(\"unable to read configuration file '{}' ({e})\", config_file.display())))?;\n\n        let root = settings::resolve_root(config_file);\n        let raw = parse_raw(&content, &root)?;\n\n        for option in [\"MONITOR_INTERFACE\", \"CAPTURE_BUFFER\", \"LOG_DIR\"] {\n            if !raw.contains_key(option) {\n                bail!(\"missing mandatory option '{option}' in configuration file '{}'\", config_file.display());\n            }\n        }\n\n        for name in unknown_keys(&raw) {\n            // A typo'd name parses fine and is then ignored - the feature it was meant to\n            // configure just stays off while the file looks correct. Warn rather than fail: an\n            // older config meeting a newer sensor (or the reverse) must keep working.\n            crate::cprintln!(\n                \"[!] unknown configuration option '{}' in configuration file '{}' (typo? see 'maltrail.conf' for the accepted names)\",\n                name,\n                config_file.display()\n            );\n        }\n\n        let capture_buffer_raw = get_str(&raw, \"CAPTURE_BUFFER\");\n        let capture_buffer = if capture_buffer_raw.is_empty() {\n            0\n        } else {","sourceCodeStart":727,"sourceCodeEnd":763,"githubUrl":"https://github.com/stamparm/maltrail/blob/77cfb06d7606506d101bbcec0786c77166c4255e/sensor/src/config.rs#L727-L763","documentation":"The sensor's configuration parser requires three mandatory options: MONITOR_INTERFACE, CAPTURE_BUFFER and LOG_DIR. During config load it iterates this list and, if any key is absent from the raw parsed configuration, it bails with this message naming the missing option and the config file path. The library fails fast instead of guessing defaults, since these options have no safe defaults for a monitoring sensor.","triggerScenarios":"Loading a sensor config file (parse_raw path in sensor/src/config.rs) that lacks any of the keys MONITOR_INTERFACE, CAPTURE_BUFFER, or LOG_DIR. Occurs when the config file is truncated, hand-edited and a section was deleted, or a new install was never fully populated.","commonSituations":"Fresh deployment with a minimal/incomplete config; config copied from an older sensor version where an option was named differently; a line was commented out while debugging; file was overwritten by a template missing these keys.","solutions":["Open the config file named in the error and add the missing option key shown in the message (e.g. MONITOR_INTERFACE=eth0).","Compare the file against a known-good sample config to spot any other missing mandatory keys (all three are validated in one pass, but the first missing one aborts).","Verify the sensor is reading the intended file: resolve_root may redirect a relative config path; check that you edited the file actually being loaded.","If upgrading from an older sensor version, migrate renamed/removed keys to the current names."],"exampleFix":"// before (config.conf, missing keys)\nLOG_DIR=/var/log/sensor\n\n// after (config.conf)\nMONITOR_INTERFACE=eth0\nCAPTURE_BUFFER=128\nLOG_DIR=/var/log/sensor","handlingStrategy":"validation","validationCode":"const MANDATORY: &[&str] = &[\"MONITOR_INTERFACE\", \"CAPTURE_BUFFER\", \"LOG_DIR\"];\nlet raw = parse_raw(&content, &root)?;\nlet missing: Vec<_> = MANDATORY.iter().filter(|k| !raw.contains_key(**k)).collect();\nif !missing.is_empty() {\n    return Err(format!(\"config file {} missing: {}\", config_file.display(), missing.join(\", \")));\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Start from the shipped sample config and never delete mandatory keys.","Diff your config against a known-good one before deploying.","Run a config-validation step (sensor --check-config) in CI or startup scripts.","Track config schema changes when upgrading sensor versions."],"tags":["rust","configuration","startup"],"backgroundTag":"missing-required-config-field","analyzedSha":"77cfb06d7606506d101bbcec0786c77166c4255e","analyzedAt":"2026-09-13T03:50:16.010Z","contentChangedAt":"2026-09-13T03:50:16.010Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}