{"record":{"id":"5bfd9a2da41ba725","repo":"Hmbown/CodeWhale","slug":"could-not-snapshot-the-codewhale-owned-legacy-slot-secret","errorCode":null,"errorMessage":"could not snapshot the Codewhale-owned legacy {slot} secret slot before clearing it: {error}; config was not changed","messagePattern":"could not snapshot the Codewhale-owned legacy (.+?) secret slot before clearing it: (.+?); config was not changed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/cli/src/lib.rs","lineNumber":2688,"sourceCode":"        println!(\"cleared xAI credentials from config, secret store, and owned OAuth storage\");\n    } else {\n        println!(\"cleared API key for {slot} from config and secret store\");\n    }\n    Ok(())\n}\n\n/// Remove only Codewhale-owned state for the retired Antigravity route.\n///\n/// This deliberately operates on the already-loaded Codewhale config and its\n/// own secret slot. It never resolves an external credential path, reads an\n/// environment credential, or invokes a Google/Antigravity logout or revoke\n/// flow.\nfn clear_legacy_antigravity_config(store: &mut ConfigStore, secrets: &Secrets) -> Result<()> {\n    let provider = ProviderKind::Antigravity;\n    let slot = provider_slot(provider);\n    let original_config = store.config.clone();\n    let prior_secret = secrets.get(slot).map_err(|error| {\n        anyhow!(\n            \"could not snapshot the Codewhale-owned legacy {slot} secret slot before clearing it: {error}; config was not changed\"\n        )\n    })?;\n\n    store.config.providers.antigravity = Default::default();\n    store\n        .config\n        .fallback_providers\n        .retain(|fallback| *fallback != provider);\n    if store.config.provider == provider {\n        store.config.provider = ProviderKind::default();\n        store.config.selected_provider_id = None;\n    }\n\n    if let Err(error) = secrets.delete(slot) {\n        store.config = original_config;\n        return Err(anyhow!(\n            \"could not clear the Codewhale-owned legacy {slot} secret slot: {error}; config was not changed\"","sourceCodeStart":2670,"sourceCodeEnd":2706,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/cli/src/lib.rs#L2670-L2706","documentation":"clear_legacy_antigravity_config migrates away from the legacy Antigravity provider config. Before changing anything it snapshots the existing secret slot via secrets.get(slot); if that read fails, it aborts the whole migration with this message so the config is left untouched. This is a safety checkpoint: never clear a secret you could not first read back.","triggerScenarios":"`secrets.get(slot)` for the Antigravity slot returns Err — the secret backend (keyring/OS agent) is unavailable, locked, or returns an IO error during the legacy-config cleanup migration.","commonSituations":"Running the legacy migration on a headless machine without a keyring service, a locked keychain prompting for access, or a corrupted secret store entry.","solutions":["Ensure the OS secret service/keyring is running and unlocked, then retry the migration","Unlock the keychain or grant the CLI access to the slot if access control blocked the read","Fix or reset the secret backend; verify `secrets.get` works for the slot","Skip/defer the legacy migration until the backend is healthy — config remains unchanged"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// preflight: verify the slot is readable before triggering the migration\nlet probe = secrets.get(provider_slot(ProviderKind::Antigravity));\nif probe.is_err() { eprintln!(\"secret backend unavailable; defer legacy cleanup\"); }","typeGuard":null,"tryCatchPattern":"match clear_legacy_antigravity_config(store, secrets) {\n    Err(e) if e.to_string().contains(\"snapshot\") => {\n        eprintln!(\"secret store unreadable — config left unchanged; fix keyring and retry\");\n    }\n    other => other?,\n}","preventionTips":["Ensure the keyring/secret service is running and unlocked before running migrations","Run migrations interactively the first time so keychain access prompts can be approved","Monitor secret-backend health on headless hosts where migrations run unattended"],"tags":["secrets","migration","keyring"],"backgroundTag":"file-read-failed","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}