stamparm/maltrail · error
write config
Error message
write config
What it means
with_options_in() renders the harness configuration (harness.conf) from a template plus options.extra lines and panics with "write config" if std::fs::write fails. This is the final filesystem setup step before Config::load, so a panic here means the harness environment could not be materialized at all.
Solutions
- Check temp-dir free space and permissions before running harness tests
- Inspect options.extra lines for malformed config content and fix the caller-supplied options
- Give each test run a dedicated TMPDIR to avoid cross-run temp collisions
- Include the config path and io::Error in the panic message
Example fix
// before
std::fs::write(&config_file, config_text).expect("write config");
// after
std::fs::write(&config_file, &config_text)
.unwrap_or_else(|e| panic!("write config {}: {e}\n--- config ---\n{config_text}", config_file.display())); Defensive patterns
Strategy: validation
Validate before calling
assert!(!options.extra.iter().any(|l| l.trim().is_empty() || l.contains('\0')), "invalid extra config line"); Try / catch
std::fs::write(&config_file, &config_text).unwrap_or_else(|e| panic!("write config {}: {e}", config_file.display())); Prevention
- Validate HarnessOptions::extra lines before building the harness
- Reserve temp-disk headroom in CI
- Keep harness dir lifetimes contained to the test to avoid cross-run collisions
When it happens
Trigger: Calling Harness::write/with_options_in() when writing dir/harness.conf fails due to permissions, disk-full, a read-only filesystem, or the harness dir disappearing mid-setup (external temp cleaner, parallel test collision on the same pid).
Common situations: Disk-full CI machines; extra config lines in HarnessOptions::extra containing path separators or characters that make the rendered config invalid; concurrent harness instances colliding after a pid reuse in containers.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
AI-assisted analysis of stamparm/maltrail@77cfb06d76 (2026-09-13).
Data as JSON: /api/errors/ad4e29239e0b92d7.
Report an issue: GitHub.
Appendix: source
Thrown at sensor/src/testkit.rs:127
USE_CONDENSED_STORAGE false\n\
SENSOR_NAME harness\n\
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));View on GitHub (pinned to 77cfb06d76)