From c6d0b412a0808cfb6a6cfc9579caa96bb95f57be Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 29 Oct 2025 11:39:23 -0400 Subject: [PATCH] Limit `uv auth login pyx.dev` retries to 60s (#16498) ## Summary Without this, a user who does `uv auth login ...` will retry against the service's status endpoint forever. This probably isn't what they intended (they probably walked away from their machine), so we end their login initiation session after 60 retries. Since we do a retry every second, this gives them no less than a minute to complete a login (which should be more than enough). ## Test Plan We don't have browser-negotiated login tests at the moment in CI, but I've tested this locally: ```console % ./target/debug/uv auth login pyx.dev Logging in with https://api.pyx.dev/auth/cli/login/REDACTED error: Login session timed out ``` (That took well over a minute, so 60s is a lower bound assuming a very optimal network roundtrip on each poll.) --------- Signed-off-by: William Woodruff --- crates/uv/src/commands/auth/login.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/crates/uv/src/commands/auth/login.rs b/crates/uv/src/commands/auth/login.rs index c0d937e7c..3e708c7b0 100644 --- a/crates/uv/src/commands/auth/login.rs +++ b/crates/uv/src/commands/auth/login.rs @@ -19,6 +19,9 @@ use crate::commands::ExitStatus; use crate::printer::Printer; use crate::settings::NetworkSettings; +// We retry no more than this many times when polling for login status. +const STATUS_RETRY_LIMIT: u32 = 60; + /// Login to a service. pub(crate) async fn login( service: Service, @@ -215,6 +218,7 @@ pub(crate) async fn pyx_login_with_browser( url }; + let mut retry = 0; let credentials = loop { let response = client .for_host(store.api()) @@ -225,6 +229,7 @@ pub(crate) async fn pyx_login_with_browser( // Retry on 404. reqwest::StatusCode::NOT_FOUND => { tokio::time::sleep(std::time::Duration::from_secs(1)).await; + retry += 1; } // Parse the credentials on success. _ if response.status().is_success() => { @@ -236,6 +241,12 @@ pub(crate) async fn pyx_login_with_browser( break Err(anyhow::anyhow!("Failed to login with code `{status}`")); } } + + if retry >= STATUS_RETRY_LIMIT { + break Err(anyhow::anyhow!( + "Login session timed out after {STATUS_RETRY_LIMIT} seconds" + )); + } }?; store.write(&credentials).await?;