zeroclaw-labs/zeroclaw · error
Pending {} login is missing code verifier
Error message
Pending {} login is missing code verifier What it means
load_pending_oauth_login reconstructs a PendingOAuthLogin from the persisted auth-<provider>-pending.json file. The PKCE code_verifier is mandatory to finish the OAuth exchange; it is read either from encrypted_code_verifier (decrypted via the secret store) or the legacy plaintext code_verifier field. If the file has neither field, resuming the login is impossible, so it bails with the provider name in the message.
Source
Thrown at crates/zeroclaw-providers/src/auth/mod.rs:985
config: &Config,
model_provider: &str,
) -> Result<Option<PendingOAuthLogin>> {
let path = pending_oauth_login_path(config, model_provider);
if !path.exists() {
return Ok(None);
}
let bytes = std::fs::read(&path)?;
if bytes.is_empty() {
return Ok(None);
}
let persisted: PendingOAuthLoginFile = serde_json::from_slice(&bytes)?;
let secret_store = pending_oauth_secret_store(config);
let code_verifier = if let Some(encrypted) = persisted.encrypted_code_verifier {
secret_store.decrypt(&encrypted)?
} else if let Some(plaintext) = persisted.code_verifier {
plaintext
} else {
anyhow::bail!("Pending {} login is missing code verifier", model_provider);
};
Ok(Some(PendingOAuthLogin {
model_provider: persisted
.model_provider
.unwrap_or_else(|| model_provider.to_string()),
profile: persisted.profile,
code_verifier,
state: persisted.state,
created_at: persisted.created_at,
}))
}
pub fn clear_pending_oauth_login(config: &Config, model_provider: &str) {
let path = pending_oauth_login_path(config, model_provider);
if let Ok(file) = std::fs::OpenOptions::new().write(true).open(&path) {
let _ = file.set_len(0);
let _ = file.sync_all();
}View on GitHub (pinned to 88bb9c8533)
Solutions
- Discard the stale pending state by deleting auth-<provider>-pending.json under the zeroclaw state dir, then re-run `zeroclaw auth login --model-provider <provider>`
- Keep the state dir and secret store (which decrypts encrypted_code_verifier) on the same machine/profile — moving only the JSON without the secret store makes the verifier unrecoverable
- Complete the paste-redirect step in the same session/environment where `auth login` started
Example fix
# before: resuming a stale pending login zeroclaw auth paste-redirect --model-provider gemini # after: clear it and start fresh rm "$(zeroclaw auth state-dir)/auth-gemini-pending.json" zeroclaw auth login --model-provider gemini
Defensive patterns
Strategy: validation
Validate before calling
let path = state_dir.join(format!("auth-{provider}-pending.json"));
if path.exists() {
let raw: serde_json::Value = serde_json::from_str(&std::fs::read_to_string(&path)?)?;
let has_verifier = raw.get("encrypted_code_verifier").is_some_and(|v| !v.is_null())
|| raw.get("code_verifier").is_some_and(|v| !v.is_null());
anyhow::ensure!(has_verifier, "pending login for {provider} lacks a code verifier — delete {path} and re-login");
} Try / catch
match auth.load_pending_oauth_login(ctx, provider, profile).await {
Ok(Some(p)) => Ok(p),
Err(e) if e.to_string().contains("missing code verifier") => {
let _ = std::fs::remove_file(pending_path); // clear stale state
anyhow::bail!("pending login unusable — re-run `zeroclaw auth login --model-provider {provider}`");
}
other => other,
} Prevention
- Finish login and paste-redirect in the same session and environment
- When copying a state dir, copy the secret store too or pending verifiers become unreadable
- After version upgrades, delete leftover auth-*-pending.json files before resuming
When it happens
Trigger: Resuming (`auth paste-redirect`) a pending login whose state file was written by an older zeroclaw version before verifier persistence existed, a hand-crafted/truncated pending file, or a file where the encrypted field failed to serialize. paste_redirect hits this when loading the saved login.
Common situations: Upgrading zeroclaw across versions while a login was left half-finished, editing or partially copying the state dir, or disk issues truncating the JSON.
Related errors
- `auth paste-redirect` is not supported for this provider. On
- Pending login profile mismatch: pending={}, requested={}
- Nevis token_validation is 'local' but no jwks_url is configu
- oauth2 configured for '{}' but no auth service provided
- gateway registration failed ({status}): {err}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/40b9dec96a948486.
Report an issue: GitHub.