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

  1. Keep the TempDir binding alive for the whole test (tempdir removes the tree when dropped).
  2. Inspect the io::Error kind: NotFound -> missing dir, IsADirectory -> wrong target, PermissionDenied -> perms.
  3. 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

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)