Hmbown/CodeWhale · error

; additionally failed to restore prior secret-store state…

Error message

{error}; additionally failed to restore prior secret-store state for {slot}: {rollback}

What it means

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.

Solutions

  1. Read the `{rollback}` cause and restore the secret backend (restart the keyring daemon, unlock the login keyring, fix permissions).
  2. 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.
  3. Fix the original config-save `{error}` (file permissions, disk space), then re-run the persist command.
  4. If restoration is impossible, re-authenticate the provider to write a fresh key rather than trying to recover the old one.

Example fix

// before: rollback assumes the backend that just wrote is still writable
match prior_secret.expect("snapshot succeeded") {
    Some(prev) => secrets.set(slot, &prev),
    None => secrets.delete(slot),
}
// after: surface a targeted hint when the rollback write fails
.map_err(|rollback| anyhow!(
    "{error}; rollback write to secret backend failed: {rollback} - check that your keyring service is running and unlocked"
))?
Defensive patterns

Strategy: try-catch

Validate before calling

// Rust: confirm the backend is both readable and writable before a transaction
secrets.get(slot).map_err(|e| anyhow!("backend read check failed: {e}"))?;
secrets.set(slot, "codewhale-preflight-probe")
    .and_then(|_| secrets.delete(slot))
    .map_err(|e| anyhow!("backend write check failed: {e}"))?;

Try / catch

// Rust
match persist_provider_api_key(&mut store, &secrets, provider, &api_key) {
    Ok(_) => {}
    Err(e) if e.to_string().contains("failed to restore prior secret-store state") => {
        eprintln!("rollback write failed; manually reconcile slot '{slot}' with a keyring tool: {e:#}");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: 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()`.

Common situations: 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.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/5bfb3b0da9a26e33. Report an issue: GitHub.

Appendix: source

Thrown at crates/cli/src/lib.rs:2748

                "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.",
                codewhale_config::quote_os_path(store.path())
            ));
        }
    };
    if let Err(error) = store.save() {
        store.config = original_config;
        if secret_store_saved {
            let current = secrets
                .get(slot)
                .map_err(|rollback| anyhow::anyhow!(
                    "{error}; additionally could not verify secret-store rollback for {slot}: {rollback}"
                ))?;
            if current.as_deref() == Some(api_key) {
                match prior_secret.expect("snapshot succeeded before secret write") {
                    Some(previous) => secrets.set(slot, &previous),
                    None => secrets.delete(slot),
                }
                .map_err(|rollback| anyhow::anyhow!(
                    "{error}; additionally failed to restore prior secret-store state for {slot}: {rollback}"
                ))?;
            }
        }
        return Err(error);
    }
    codewhale_config::scrub_plaintext_api_keys_from_config_backup(store.path())?;
    Ok(secret_store_saved)
}

fn clear_auth_provider(
    store: &mut ConfigStore,
    secrets: &Secrets,
    provider: ProviderKind,
) -> Result<()> {
    if provider == ProviderKind::Antigravity {
        return clear_legacy_antigravity_config(store, secrets);
    }

View on GitHub (pinned to 433685b202)