Hmbown/CodeWhale · warning

scrub backup

Error message

scrub backup

What it means

Second expect in the same test: fs::write(&backup_path, ...).expect("scrub backup") is actually labeled on the write of the backup contents; the expect("scrub backup") on the following line belongs to scrub_plaintext_api_keys_from_config_backup itself. A panic here means either the fixture write failed or the scrub function returned an Err while cleaning plaintext api_key entries from the config backup file.

Solutions

  1. Read the wrapped io/parse error in the panic; if it comes from scrub, verify the backup content is valid TOML the scrubber accepts.
  2. Confirm scrub_plaintext_api_keys_from_config_backup still rewrites the file atomically after parsing.
  3. Run the test alone to exclude parallel interference.
Defensive patterns

Strategy: validation

Validate before calling

let backup_toml: toml::Value = toml::from_str(&fs::read_to_string(&backup_path)?)?;
// valid TOML before handing it to scrub

Try / catch

scrub_plaintext_api_keys_from_config_backup(&path)
    .unwrap_or_else(|e| panic!("scrub backup failed: {e}; is the backup valid TOML?"));

Prevention

When it happens

Trigger: scrub_plaintext_api_keys_from_config_backup fails when the backup file is unreadable, unparseable as TOML, or cannot be rewritten; the fixture write can also fail for the same reasons as 2844.

Common situations: Changing the backup format so scrub's TOML parse fails; a regression in scrub leaving the file locked or read-only; CI filesystem issues.

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/4d343e959cd39a0e. Report an issue: GitHub.

Appendix: source

Thrown at crates/config/src/tests.rs:4205

    );
    assert!(backup.contains("api_key_env = \"OPENROUTER_API_KEY\""));
    assert!(backup.contains("auth_mode = \"api_key\""));
    assert!(backup.contains("default_text_model = \"deepseek-v4-pro\""));
}

#[test]
fn config_backup_scrub_repairs_an_existing_plaintext_backup() {
    let dir = tempfile::tempdir().expect("tempdir");
    let path = dir.path().join(CONFIG_FILE_NAME);
    fs::write(&path, "model = \"new-model\"\n").expect("seed config");
    let backup_path = config_backup_path(&path);
    fs::write(
        &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");

View on GitHub (pinned to 433685b202)