{"record":{"id":"1c5e8bf2f53539e6","repo":"Hmbown/CodeWhale","slug":"read-backup","errorCode":null,"errorMessage":"read backup","messagePattern":"read backup","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/config/src/tests.rs","lineNumber":4207,"sourceCode":"    assert!(backup.contains(\"auth_mode = \\\"api_key\\\"\"));\n    assert!(backup.contains(\"default_text_model = \\\"deepseek-v4-pro\\\"\"));\n}\n\n#[test]\nfn config_backup_scrub_repairs_an_existing_plaintext_backup() {\n    let dir = tempfile::tempdir().expect(\"tempdir\");\n    let path = dir.path().join(CONFIG_FILE_NAME);\n    fs::write(&path, \"model = \\\"new-model\\\"\\n\").expect(\"seed config\");\n    let backup_path = config_backup_path(&path);\n    fs::write(\n        &backup_path,\n        \"api_key = \\\"old-test-credential\\\"\\nmodel = \\\"old-model\\\"\\n\",\n    )\n    .expect(\"seed backup\");\n\n    scrub_plaintext_api_keys_from_config_backup(&path).expect(\"scrub backup\");\n\n    let backup = fs::read_to_string(backup_path).expect(\"read backup\");\n    assert!(!backup.contains(\"old-test-credential\"), \"{backup}\");\n    assert!(!backup.contains(\"api_key\"), \"{backup}\");\n    assert!(backup.contains(\"model = \\\"old-model\\\"\"));\n}\n\n#[test]\nfn config_store_save_preserves_comments() {\n    let dir = tempfile::tempdir().expect(\"tempdir\");\n    let config_path = dir.path().join(CONFIG_FILE_NAME);\n    let original = \"# my model\\nmodel = \\\"deepseek-v4-flash\\\"\\n# end comment\\n\";\n    fs::write(&config_path, original).expect(\"write config\");\n\n    let mut store = ConfigStore::load(Some(config_path.clone())).expect(\"load config store\");\n    store.config.model = Some(\"deepseek-v4-pro\".to_string());\n    store.save().expect(\"save\");\n\n    let body = fs::read_to_string(&config_path).expect(\"read config\");\n    assert!(body.contains(\"# my model\"), \"prefix comment preserved\");","sourceCodeStart":4189,"sourceCodeEnd":4225,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/config/src/tests.rs#L4189-L4225","documentation":"fs::read_to_string(backup_path).expect(\"read backup\") in crates/config/src/tests.rs:4207 panics when the scrubbed backup file cannot be read back as a UTF-8 string. The receipt type ImportReceipt (crates/cli/src/config_bundles.rs:1001) exposes backup_path: Option<PathBuf>, and a None backup (apply_prepared_bundle returns backup_path: None when no backup was made) is a frequent root cause when tests are adapted to use receipt-backed paths.","triggerScenarios":"Reading backup_path when it is None (unwrap on Option before read), the file was deleted/moved by the scrub step, or the scrub wrote invalid UTF-8.","commonSituations":"Refactoring tests to derive paths from ImportReceipt.backup_path and forgetting it is Option<PathBuf>; scrub implementation change removing the backup file.","solutions":["Handle the Option: match receipt.backup_path and skip/adjust the assertion when no backup was created.","Verify the scrub step does not delete or rename the backup before the read.","Check the io::Error kind in the panic: NotFound means the file vanished; InvalidData means non-UTF-8 content."],"exampleFix":"// before\nlet backup = fs::read_to_string(backup_path).expect(\"read backup\");\n// after\nlet backup = fs::read_to_string(\n    receipt.backup_path.as_ref().expect(\"backup should exist\"),\n).expect(\"read backup\");","handlingStrategy":"type-guard","validationCode":"let Some(backup_path) = receipt.backup_path.as_deref() else {\n    eprintln!(\"no backup was created for this import\");\n    return;\n};","typeGuard":"fn backup_of(receipt: &ImportReceipt) -> Option<&std::path::Path> {\n    receipt.backup_path.as_deref()\n}","tryCatchPattern":"let backup = fs::read_to_string(backup_path)\n    .unwrap_or_else(|e| panic!(\"read backup at {backup_path:?} failed: {e}\"));","preventionTips":["Treat ImportReceipt.backup_path as Option<PathBuf> — None means no backup was made","Never delete or rename the backup between scrub and read","Check the io::Error kind: NotFound vs InvalidData (non-UTF-8)"],"tags":["test","filesystem","io","option"],"backgroundTag":"file-read-failed","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}