{"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":null,"httpStatus":null,"severity":"error","filePath":"crates/cli/src/lib.rs","lineNumber":2748,"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    if provider == ProviderKind::Antigravity {\n        return clear_legacy_antigravity_config(store, secrets);\n    }","sourceCodeStart":2730,"sourceCodeEnd":2766,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/cli/src/lib.rs#L2730-L2766","documentation":"Raised in `persist_provider_api_key_unlocked` (crates/cli/src/lib.rs:2748). After a config save failure, the code verified the secret slot still holds the newly written key and attempted to restore the prior value (`secrets.set` with the snapshot, or `secrets.delete` if there was none). This error fires when that restore write itself fails, so both the config file and the secret store are now in partially-updated states. The chained message preserves the original config-save error plus the restore error.","triggerScenarios":"Same transaction as error 2060, but the failure point is the restore write: prior secret existed -> `secrets.set(slot, previous)` errored, or no prior secret -> `secrets.delete(slot)` errored, after a failed `store.save()`.","commonSituations":"Keyring became write-locked or the dbus/keyring daemon exited between the initial set and the rollback; read-only credential store; corporate keyring policies blocking writes from CLI sessions.","solutions":["Read the `{rollback}` cause and restore the secret backend (restart the keyring daemon, unlock the login keyring, fix permissions).","Inspect the current slot value with a keyring tool; if it holds the wrong key, set or delete it manually to match the intended provider state.","Fix the original config-save `{error}` (file permissions, disk space), then re-run the persist command.","If restoration is impossible, re-authenticate the provider to write a fresh key rather than trying to recover the old one."],"exampleFix":"// before: rollback assumes the backend that just wrote is still writable\nmatch prior_secret.expect(\"snapshot succeeded\") {\n    Some(prev) => secrets.set(slot, &prev),\n    None => secrets.delete(slot),\n}\n// after: surface a targeted hint when the rollback write fails\n.map_err(|rollback| anyhow!(\n    \"{error}; rollback write to secret backend failed: {rollback} - check that your keyring service is running and unlocked\"\n))?","handlingStrategy":"try-catch","validationCode":"// Rust: confirm the backend is both readable and writable before a transaction\nsecrets.get(slot).map_err(|e| anyhow!(\"backend read check failed: {e}\"))?;\nsecrets.set(slot, \"codewhale-preflight-probe\")\n    .and_then(|_| secrets.delete(slot))\n    .map_err(|e| anyhow!(\"backend write check failed: {e}\"))?;","typeGuard":null,"tryCatchPattern":"// Rust\nmatch persist_provider_api_key(&mut store, &secrets, provider, &api_key) {\n    Ok(_) => {}\n    Err(e) if e.to_string().contains(\"failed to restore prior secret-store state\") => {\n        eprintln!(\"rollback write failed; manually reconcile slot '{slot}' with a keyring tool: {e:#}\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Ensure the keyring service stays up for the duration of long-running setup scripts.","Unlock the login keyring before scripted provider configuration.","Re-authenticate the provider instead of hand-restoring old keys when rollback fails.","Check keyring store permissions after OS upgrades."],"tags":["secret-store","keyring","rollback","restore-failed","rust"],"backgroundTag":"secret-store-rollback-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"}