{"record":{"id":"fa71d602c9ea099b","repo":"stamparm/maltrail","slug":"harness-config-must-load","errorCode":null,"errorMessage":"harness config must load","messagePattern":"harness config must load","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sensor/src/testkit.rs","lineNumber":129,"sourceCode":"             SCAN_WINDOW 30\\n\\\n             USE_HEURISTICS {}\\n\\\n             CHECK_HOST_DOMAINS {}\\n\\\n             CHECK_MISSING_HOST {}\\n\\\n             LOG_DIR {}\\n\\\n             TRAILS_FILE {}\\n\",\n            options.use_heuristics,\n            options.check_host_domains,\n            options.check_missing_host,\n            log_dir.display(),\n            trails_file.display()\n        );\n        for line in &options.extra {\n            config_text.push_str(line);\n            config_text.push('\\n');\n        }\n        std::fs::write(&config_file, config_text).expect(\"write config\");\n\n        let mut cfg = Config::load(&config_file).expect(\"harness config must load\");\n        cfg.root = root.clone();\n        let cfg = Arc::new(cfg);\n\n        settings::init(root.clone());\n        crate::output::init_error_log(&log_dir, false);\n\n        // An empty whitelist keeps fixture trails from being filtered out; the shipped\n        // whitelist is exercised separately in tests/trails.rs. A test that sets USER_WHITELIST\n        // gets it honoured, so the precedence tests can pin real whitelist-vs-trail behaviour.\n        let whitelist = Arc::new(match cfg.user_whitelist.clone() {\n            Some(p) => Whitelist::load(&root, Some(&p)),\n            None => Whitelist::default(),\n        });\n\n        let db = build_db(trails);\n        let store = Arc::new(TrailStore::new(db));\n        let view = TrailView::new(store);\n","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/stamparm/maltrail/blob/77cfb06d7606506d101bbcec0786c77166c4255e/sensor/src/testkit.rs#L111-L147","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","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"],"exampleFix":"// before\nconfig_text.push_str(\"LOG_DiR /tmp/x\\n\"); // typo key\n// after\nconfig_text.push_str(\"LOG_DIR /tmp/x\\n\");","handlingStrategy":"validation","validationCode":"fn assert_valid_config_lines(extra: &[String], valid_keys: &[&str]) {\n    for line in extra {\n        let key = line.split_whitespace().next().unwrap_or(\"\");\n        assert!(valid_keys.contains(&key), \"unknown config key: {line}\");\n    }\n}","typeGuard":null,"tryCatchPattern":"let cfg = Config::load(&config_file).unwrap_or_else(|e| panic!(\"harness config must load: {e:?}\"));","preventionTips":["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"],"tags":["rust","config","test-harness","panic"],"backgroundTag":"config-file-not-found","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"}