{"record":{"id":"5bfb3b0da9a26e33","repo":"Hmbown/CodeWhale","slug":"error-additionally-failed-to-restore-prior-secr","errorCode":null,"errorMessage":"{error}; additionally failed to restore prior secret-store state for {slot}: {rollback}","messagePattern":"(.+?); additionally failed to restore prior secret-store state for (.+?): (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"critical","filePath":"crates/cli/src/lib.rs","lineNumber":2384,"sourceCode":"                \"Secret storage snapshot failed for {slot}: {error}. Refusing to write the API key in plaintext to {}. Fix the configured secret backend and retry; Codewhale did not change that file.\",\n                codewhale_config::quote_os_path(store.path())\n            ));\n        }\n    };\n    if let Err(error) = store.save() {\n        store.config = original_config;\n        if secret_store_saved {\n            let current = secrets\n                .get(slot)\n                .map_err(|rollback| anyhow::anyhow!(\n                    \"{error}; additionally could not verify secret-store rollback for {slot}: {rollback}\"\n                ))?;\n            if current.as_deref() == Some(api_key) {\n                match prior_secret.expect(\"snapshot succeeded before secret write\") {\n                    Some(previous) => secrets.set(slot, &previous),\n                    None => secrets.delete(slot),\n                }\n                .map_err(|rollback| anyhow::anyhow!(\n                    \"{error}; additionally failed to restore prior secret-store state for {slot}: {rollback}\"\n                ))?;\n            }\n        }\n        return Err(error);\n    }\n    codewhale_config::scrub_plaintext_api_keys_from_config_backup(store.path())?;\n    Ok(secret_store_saved)\n}\n\nfn clear_auth_provider(\n    store: &mut ConfigStore,\n    secrets: &Secrets,\n    provider: ProviderKind,\n) -> Result<()> {\n    let slot = provider_slot(provider);\n    let original_config = store.config.clone();\n    clear_provider_api_key_from_config(store, provider);","sourceCodeStart":2366,"sourceCodeEnd":2402,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/cli/src/lib.rs#L2366-L2402","documentation":"Final rollback step of the same failure path: the verification read succeeded and showed the new key in the store, but restoring the prior value (set previous, or delete when the slot was previously empty) failed. The store now provably holds the new key while the config save also failed, leaving a known divergent state reported as one compound error.","triggerScenarios":"store.save() failure followed by a failing secrets.set/delete during rollback — the backend accepted the first write but rejects the undo (daemon crash, quota, permissions changed mid-operation).","commonSituations":"Keyring service restarting between write and rollback; credential store quota exceeded by the new write; sandboxed environments revoking access mid-command.","solutions":["Repair the secret backend and the config write issue, then rerun the key-set command to converge both stores","Read the slot explicitly to confirm it holds the new key before deciding to re-enter the old one manually","Check backend logs for why the undo write was rejected","Treat the message as authoritative about state: new key persisted, config not saved"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"match set_provider_key(&mut store, &mut secrets, key) {\n    Ok(_) => {}\n    Err(err) if err.to_string().contains(\"additionally failed to restore prior secret-store state\") => {\n        // Known state: store holds the NEW key, config not saved. Re-run key-set after\n        // repairing backend + config writability to converge.\n        repair_secret_backend()?;\n        repair_config_writability()?;\n        set_provider_key(&mut store, &mut secrets, key)?;\n    }\n    Err(err) => return Err(err),\n}","preventionTips":["Monitor keyring daemon stability during long-running setup automation","Avoid permission changes or sandbox kills while credential migration runs","Rerun the same command rather than hand-editing either store — it rewrites both sides deterministically"],"tags":["cli","secrets","config","rollback","consistency","rust"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}