Hmbown/CodeWhale · warning
write config
Error message
write config
What it means
fs::write(&config_path, original).expect("write config") in config_store_save_preserves_comments panics when seeding the test's config.toml fails. The fixture writes a commented TOML file to verify ConfigStore::save preserves comments; failure is purely environmental or path-related.
Solutions
- Keep the TempDir binding alive for the whole test (tempdir removes the tree when dropped).
- Inspect the io::Error kind: NotFound -> missing dir, IsADirectory -> wrong target, PermissionDenied -> perms.
- Run the single test in isolation to rule out cross-test interference.
Defensive patterns
Strategy: validation
Validate before calling
assert!(config_path.parent().map(|p| p.is_dir()).unwrap_or(false), "fixture dir missing");
Try / catch
fs::write(&config_path, original)
.unwrap_or_else(|e| panic!("write config failed ({e:?}); is the tempdir alive?")); Prevention
- Bind the TempDir to a variable and keep it alive for the whole test
- Write fixtures immediately after creating the tempdir
- Confirm the target is a file path, not a directory
When it happens
Trigger: The parent directory (from tempdir) was already dropped; config_path points at an existing directory; permissions or a full disk block the write.
Common situations: Refactoring the test so dir is dropped (tempdir deletes on drop) before writes; typos joining the path; read-only CI filesystem.
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 Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/43aeb882d69bd18c.
Report an issue: GitHub.
Appendix: source
Thrown at crates/config/src/tests.rs:4218
&backup_path,
"api_key = \"old-test-credential\"\nmodel = \"old-model\"\n",
)
.expect("seed backup");
scrub_plaintext_api_keys_from_config_backup(&path).expect("scrub backup");
let backup = fs::read_to_string(backup_path).expect("read backup");
assert!(!backup.contains("old-test-credential"), "{backup}");
assert!(!backup.contains("api_key"), "{backup}");
assert!(backup.contains("model = \"old-model\""));
}
#[test]
fn config_store_save_preserves_comments() {
let dir = tempfile::tempdir().expect("tempdir");
let config_path = dir.path().join(CONFIG_FILE_NAME);
let original = "# my model\nmodel = \"deepseek-v4-flash\"\n# end comment\n";
fs::write(&config_path, original).expect("write config");
let mut store = ConfigStore::load(Some(config_path.clone())).expect("load config store");
store.config.model = Some("deepseek-v4-pro".to_string());
store.save().expect("save");
let body = fs::read_to_string(&config_path).expect("read config");
assert!(body.contains("# my model"), "prefix comment preserved");
assert!(body.contains("# end comment"), "suffix comment preserved");
assert!(body.contains("model = \"deepseek-v4-pro\""));
}
#[test]
fn config_store_save_preserves_disabled_keys() {
let dir = tempfile::tempdir().expect("tempdir");
let config_path = dir.path().join(CONFIG_FILE_NAME);
fs::write(
&config_path,
"# my note\nmodel = \"deepseek-v4-flash\"\n# base_url = \"http://localhost:11434/v1\"\n",View on GitHub (pinned to 433685b202)