Hmbown/CodeWhale · critical

; additionally the Codewhale-owned legacy secret slot…

Error message

{error}; additionally the Codewhale-owned legacy {slot} secret slot changed concurrently and was not overwritten during rollback

What it means

During rollback of the Codewhale-owned legacy secret slot, the code re-reads the current slot value and refuses to overwrite it if it changed concurrently. This guard prevents clobbering a value another process wrote while rollback was in flight. The error surfaces instead of silently overwriting live data.

Solutions

  1. Ensure only one CLI/updater instance operates on the secret slot at a time (close other sessions, stop background refresh).
  2. Decide which value is correct; manually set the slot if the concurrent write should be kept.
  3. Re-run the operation after the concurrent writer is gone.
  4. If the concurrent value is stale, delete it and let the retry re-establish the previous value.
Defensive patterns

Strategy: validation

Validate before calling

// before rolling back, check the slot is untouched
let current = secrets.get(slot)?;
if current.as_deref() != Some(previous.as_str()) {
    eprintln!("slot changed concurrently; resolve manually before rollback");
}

Try / catch

match result {
    Err(ConcurrentSlotWrite) => {
        // prompt user: keep new value or force restore
    }
    other => other,
}

Prevention

When it happens

Trigger: While a failed operation is being rolled back, another process or CLI instance writes a new value into the same legacy secret slot, so current != previous and the rollback refuses to proceed.

Common situations: Two instances of the CLI (or an updater and a running session) racing over the same credential slot; a scheduled token-refresh daemon updating the secret during a migration rollback.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/a62949680d00a22f. Report an issue: GitHub.

Appendix: source

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

    }

    if let Err(error) = store.save() {
        store.config = original_config;
        if let Some(previous) = prior_secret {
            let current = secrets.get(slot).map_err(|rollback| {
                anyhow!(
                    "{error}; additionally could not verify rollback of the Codewhale-owned legacy {slot} secret slot: {rollback}"
                )
            })?;
            match current {
                None => secrets.set(slot, &previous).map_err(|rollback| {
                    anyhow!(
                        "{error}; additionally failed to restore the Codewhale-owned legacy {slot} secret slot: {rollback}"
                    )
                })?,
                Some(current) if current == previous => {}
                Some(_) => {
                    return Err(anyhow!(
                        "{error}; additionally the Codewhale-owned legacy {slot} secret slot changed concurrently and was not overwritten during rollback"
                    ));
                }
            }
        }
        return Err(error);
    }

    codewhale_config::scrub_plaintext_api_keys_from_config_backup(store.path())?;
    codewhale_config::scrub_legacy_antigravity_from_config_backup(store.path())?;
    println!(
        "cleared Codewhale-owned legacy Antigravity config, consent, selection, fallback entries, and secret-store slot; Google and Antigravity sessions were not read, revoked, or changed. For Gemini, configure provider google and set GEMINI_API_KEY"
    );
    Ok(())
}

fn provider_env_set(provider: ProviderKind) -> bool {
    provider_env_value(provider).is_some()

View on GitHub (pinned to 73e0f67d83)