stamparm/maltrail · error · ConfigError
missing configuration file
Error message
missing configuration file '{}' What it means
Config::load requires the given path to be an existing regular file. If it isn't, it bails with ConfigError 'missing configuration file ...' before attempting to read. This is the sensor's first gate when starting with a config path, distinguishing a missing file from an unreadable one (which produces a different message).
Solutions
- Verify the path exists: ls the exact path you pass and create the config if missing (copy sensor.conf example)
- Use an absolute path for --config to avoid CWD-dependent resolution
- Check your deployment/startup script actually wrote the config before launching the sensor
- Confirm the path points to a file, not a directory
Example fix
// before
let cfg = Config::load(Path::new("sensor.conf"))?;
// after
let path = PathBuf::from("sensor.conf");
assert!(path.is_file(), "missing config at {}", path.display());
let cfg = Config::load(&path)?; Defensive patterns
Strategy: validation
Validate before calling
use std::path::{Path, PathBuf};
fn ensure_config(path: &Path) -> Option<PathBuf> {
if path.is_file() { Some(path.to_path_buf()) } else { None }
} Try / catch
match Config::load(&config_file) {
Ok(cfg) => cfg,
Err(ConfigError(msg)) if msg.starts_with("missing configuration file") => {
eprintln!("[!] {msg}; pass -c with a valid path");
std::process::exit(2);
}
Err(e) => return Err(e),
} Prevention
- Use absolute config paths in services and scripts
- Ensure deploy steps generate the config before starting the sensor
- Check path.is_file() before launching with a custom -c value
When it happens
Trigger: Starting the sensor (or calling Config::load) with a path that does not exist or is a directory — wrong -c/--config value, config file deleted, relative path resolved against an unexpected working directory, or a config generated at runtime that wasn't created yet.
Common situations: Passing a default config path that was never created; running the binary from a different CWD so a relative path breaks; a service/deploy step that should generate sensor.conf failed silently; typo in the config filename.
Understand the failure class
Background: "Config file not found": what it means and how to fix it in docker-sync, Maven, Vagrant, Turborepo and other tools — this error's family across 60 libraries.
Related errors
- invalid USERS entry ' ' [?] (hint: add whitespace at start…
- invalid configuration
- missing mandatory option
- invalid configuration value for 'LOG_SERVER
- invalid configuration value for 'SYSLOG_SERVER
AI-assisted analysis of stamparm/maltrail@77cfb06d76 (2026-09-13).
Data as JSON: /api/errors/cf1f0811032793d6.
Report an issue: GitHub.
Appendix: source
Thrown at sensor/src/config.rs:734
/// semicolons or whitespace. `core/log.py:_endpoints()` splits the same way.
pub fn split_endpoints(value: &str) -> Vec<&str> {
value.split([',', ';', ' ', '\t', '\n', '\r']).map(str::trim).filter(|s| !s.is_empty()).collect()
}
/// `sensor.py:_cfg_bool()` — for switches without a boolean-implying prefix.
pub fn cfg_bool(value: Option<&Value>) -> bool {
match value {
Some(Value::Bool(b)) => *b,
Some(Value::Int(i)) => *i == 1,
Some(Value::Str(s)) => matches!(s.trim().to_ascii_lowercase().as_str(), "1" | "true" | "yes" | "on"),
_ => false,
}
}
impl Config {
pub fn load(config_file: &Path) -> Result<Config, ConfigError> {
if !config_file.is_file() {
bail!("missing configuration file '{}'", config_file.display());
}
crate::cprintln!("[i] using configuration file '{}'", config_file.display());
let content = std::fs::read_to_string(config_file)
.map_err(|e| ConfigError(format!("unable to read configuration file '{}' ({e})", config_file.display())))?;
let root = settings::resolve_root(config_file);
let raw = parse_raw(&content, &root)?;
for option in ["MONITOR_INTERFACE", "CAPTURE_BUFFER", "LOG_DIR"] {
if !raw.contains_key(option) {
bail!("missing mandatory option '{option}' in configuration file '{}'", config_file.display());
}
}
for name in unknown_keys(&raw) {
// A typo'd name parses fine and is then ignored - the feature it was meant to
// configure just stays off while the file looks correct. Warn rather than fail: an
// older config meeting a newer sensor (or the reverse) must keep working.View on GitHub (pinned to 77cfb06d76)