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

  1. Check temp-dir free space and permissions before running harness tests
  2. Inspect options.extra lines for malformed config content and fix the caller-supplied options
  3. Give each test run a dedicated TMPDIR to avoid cross-run temp collisions
  4. 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

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)