stamparm/maltrail · error
harness config must load
Error message
harness config must load
What it means
Panic raised by `.expect("harness config must load")` when the test harness writes a synthesized config file plus any `options.extra` lines and calls `Config::load`, which returns Err (parse or validation failure). The harness aborts because a malformed test config means the fixture itself is broken.
Solutions
- Inspect the extra lines passed via TestOptions and validate each against the keys Config::load accepts
- Print the generated config file contents before Config::load to see the exact offending line
- Check the parse error returned by Config::load by temporarily replacing expect with a match that panics with the Err payload
- Update the extra line to valid `KEY value` syntax recognized by the config parser
Example fix
// before
config_text.push_str("LOG_DiR /tmp/x\n"); // typo key
// after
config_text.push_str("LOG_DIR /tmp/x\n"); Defensive patterns
Strategy: validation
Validate before calling
fn assert_valid_config_lines(extra: &[String], valid_keys: &[&str]) {
for line in extra {
let key = line.split_whitespace().next().unwrap_or("");
assert!(valid_keys.contains(&key), "unknown config key: {line}");
}
} Try / catch
let cfg = Config::load(&config_file).unwrap_or_else(|e| panic!("harness config must load: {e:?}")); Prevention
- Keep the set of valid config keys in one constant shared by tests and the parser
- Print the generated config file path and contents on failure
- Add a test that each extra option line used in the suite parses
When it happens
Trigger: `with_options_in` called with `options.extra` lines that are not valid `KEY value` config directives (unknown key, missing value, bad separator, or invalid value type), producing a Config::load failure.
Common situations: Adding a new option line to a test that typos the config key; pasting production config syntax the parser doesn't accept; a Config::load change that newly rejects a previously tolerated key.
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
- worker config must load
- write config
- write worker config
- invalid configuration value for 'OFFLINE_TIMESTAMPS
- must load
AI-assisted analysis of stamparm/maltrail@77cfb06d76 (2026-09-13).
Data as JSON: /api/errors/fa71d602c9ea099b.
Report an issue: GitHub.
Appendix: source
Thrown at sensor/src/testkit.rs:129
SCAN_WINDOW 30\n\
USE_HEURISTICS {}\n\
CHECK_HOST_DOMAINS {}\n\
CHECK_MISSING_HOST {}\n\
LOG_DIR {}\n\
TRAILS_FILE {}\n",
options.use_heuristics,
options.check_host_domains,
options.check_missing_host,
log_dir.display(),
trails_file.display()
);
for line in &options.extra {
config_text.push_str(line);
config_text.push('\n');
}
std::fs::write(&config_file, config_text).expect("write config");
let mut cfg = Config::load(&config_file).expect("harness config must load");
cfg.root = root.clone();
let cfg = Arc::new(cfg);
settings::init(root.clone());
crate::output::init_error_log(&log_dir, false);
// An empty whitelist keeps fixture trails from being filtered out; the shipped
// whitelist is exercised separately in tests/trails.rs. A test that sets USER_WHITELIST
// gets it honoured, so the precedence tests can pin real whitelist-vs-trail behaviour.
let whitelist = Arc::new(match cfg.user_whitelist.clone() {
Some(p) => Whitelist::load(&root, Some(&p)),
None => Whitelist::default(),
});
let db = build_db(trails);
let store = Arc::new(TrailStore::new(db));
let view = TrailView::new(store);
View on GitHub (pinned to 77cfb06d76)