zeroclaw-labs/zeroclaw · error
User denied authorization
Error message
User denied authorization
What it means
While polling the Google token endpoint during the device flow, the response carried error=access_denied. Google returns this when the user actively rejects the consent prompt (clicks Cancel/Deny) or when the app is blocked from consent. The poll loop maps that specific error code to this bail, ending the flow immediately.
Source
Thrown at crates/zeroclaw-providers/src/auth/gemini_oauth.rs:307
return Ok(TokenSet {
access_token: token_response.access_token,
refresh_token: token_response.refresh_token,
id_token: token_response.id_token,
expires_at,
token_type: token_response.token_type.or_else(|| Some("Bearer".into())),
scope: token_response.scope,
});
}
if let Ok(err) = serde_json::from_str::<OAuthErrorResponse>(&body) {
match err.error.as_str() {
"authorization_pending" => {}
"slow_down" => {
tokio::time::sleep(Duration::from_secs(5)).await;
}
"access_denied" => {
anyhow::bail!("User denied authorization");
}
"expired_token" => {
anyhow::bail!("Device code expired");
}
_ => {
anyhow::bail!(
"Google OAuth error: {} - {}",
err.error,
err.error_description.unwrap_or_default()
);
}
}
}
}
}
/// Receive OAuth code via loopback callback OR manual stdin input.
/// If the callback server can't receive the redirect (e.g., remote/headless environment),View on GitHub (pinned to 88bb9c8533)
Solutions
- Re-run auth login --device-code and click Allow/Continue on the consent screen this time
- If the app is unverified, complete OAuth verification or add the test user to the Google Cloud consent screen
- If a workspace policy blocks the app, use an account outside that workspace or ask the admin to allowlist the client id
Defensive patterns
Strategy: try-catch
Try / catch
match poll_device_code_tokens(client, id, secret, &device).await {
Ok(tokens) => tokens,
Err(e) if e.to_string() == "User denied authorization" => {
eprintln!("consent was denied; re-run the login and click Allow");
return Err(e);
}
Err(e) => return Err(e),
} Prevention
- Tell the user exactly which consent screen to expect before starting the flow
- Add the account as a test user while the OAuth app is in testing mode
- Do not auto-retry a denial in a loop — it needs a human decision
When it happens
Trigger: poll_device_code_tokens receives an OAuthErrorResponse whose error field is exactly "access_denied" after the user clicked deny on the Google consent screen, or after an admin policy auto-denied the OAuth client.
Common situations: User changes their mind at the consent screen; the Google Cloud OAuth app is unverified and the user backs out of the warning screen; a workspace admin disabled third-party access so consent is denied automatically.
Related errors
- Google device code request failed ({}): {}
- Device code expired before authorization was completed
- Device code expired
- xAI device-code authorization was denied
- OAuth state mismatch
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/46b4777cc0738b19.
Report an issue: GitHub.