{"record":{"id":"4987060efc632f72","repo":"Hmbown/CodeWhale","slug":"stage-setup-state","errorCode":null,"errorMessage":"stage setup state","messagePattern":"stage setup state","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/config/src/tests.rs","lineNumber":4302,"sourceCode":"    let config_path = dir.path().join(CONFIG_FILE_NAME);\n    let state_path = dir.path().join(crate::setup_state::SETUP_STATE_FILE_NAME);\n    fs::write(\n        &config_path,\n        \"# my model\\nmodel = \\\"deepseek-v4-flash\\\"\\n# end comment\\n\",\n    )\n    .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\n    let mut transaction = persistence::SetupTransaction::new();\n    transaction.stage(\n        &config_path,\n        store.rendered_body().expect(\"rendered body\").into_bytes(),\n    );\n    transaction\n        .stage_json(&state_path, &SetupState::default())\n        .expect(\"stage setup state\");\n    transaction.commit().expect(\"commit\");\n\n    let body = fs::read_to_string(&config_path).expect(\"read config\");\n    assert!(body.contains(\"# my model\"), \"prefix comment preserved\");\n    assert!(body.contains(\"# end comment\"), \"suffix comment preserved\");\n    assert!(body.contains(\"model = \\\"deepseek-v4-pro\\\"\"));\n    assert!(state_path.exists(), \"sibling setup state written\");\n}\n\n#[test]\nfn setup_transaction_rolls_back_config_store_body_on_sibling_failure() {\n    // #3410 rollback expectation: when a sibling stage fails to apply, the\n    // already-written config.toml is restored byte-for-byte, comments and\n    // all — no half-applied setup.\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\");","sourceCodeStart":4284,"sourceCodeEnd":4320,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/config/src/tests.rs#L4284-L4320","documentation":"This panic comes from `.expect(\"stage setup state\")` on `SetupTransaction::stage_json(&state_path, &SetupState::default())` at crates/config/src/tests.rs:4302. `stage_json` serializes the value to JSON and stages the bytes for atomic application at commit. It fails when `SetupState` cannot be serialized to JSON or the staged path is invalid/unwritable by transaction rules.","triggerScenarios":"Staging a `SetupState` value that fails serde JSON serialization, or a `state_path` whose parent directory does not exist or is not a directory (in this test's sibling test, a regular file 'blocker' occupies the parent slot to force failure).","commonSituations":"A serde rename/skip misconfiguration making a field unserializable; pointing stage_json at a path under a file rather than a directory; a stale path from a removed tempdir.","solutions":["Check that the state path's parent is a real directory","Verify SetupState derives Serialize and every field is JSON-serializable","Confirm the tempdir is still alive at staging time"],"exampleFix":"// before\ntransaction.stage_json(&state_path, &SetupState::default()).expect(\"stage setup state\");\n// after\nassert!(state_path.parent().map_or(false, |p| p.is_dir()), \"state parent not a directory\");\ntransaction.stage_json(&state_path, &SetupState::default())\n    .map_err(|e| panic!(\"stage setup state: {e:#}\"))\n    .unwrap();","handlingStrategy":"validation","validationCode":"assert!(state_path.parent().map_or(false, |p| p.is_dir()), \"state parent must be a directory\");\nserde_json::to_vec(&SetupState::default()).map_err(|e| format!(\"SetupState not serializable: {e}\"))?;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep Serialize derived on SetupState and all its fields","Stage only paths whose parents exist and are directories","Test serialization of default values after schema changes"],"tags":["rust","serde","json","setup-transaction"],"backgroundTag":"json-serialization-failed","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}