astral-sh/uv · error

Failed to login with code `{status}`

Error message

Failed to login with code `{status}`

What it means

Raised by the browser-based pyx login flow (`uv login` against a pyx-hosted index). After opening the auth/cli/login URL, uv polls auth/cli/status every second; a 404 means 'not yet completed' and retries, a 2xx returns tokens, but any other HTTP status (e.g., 500, 401, 410) breaks the loop with this error, embedding the raw status code. It signals a server-side or session problem, not a client timeout.

Source

Thrown at crates/uv/src/commands/auth/login.rs:233

        let response = client
            .for_host(store.api())
            .get(Url::from(url.clone()))
            .send()
            .await?;
        match response.status() {
            // 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() => {
                let credentials = response.json::<PyxOAuthTokens>().await?;
                break Ok::<PyxTokens, anyhow::Error>(PyxTokens::OAuth(credentials));
            }
            // Fail on any other status code (like a 500).
            status => {
                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?;

    Ok(AccessToken::from(credentials))
}

View on GitHub (pinned to f1a42680ff)

Solutions

  1. Re-run `uv login` to start a fresh login session (the old cli_token is likely dead) and complete the browser prompt promptly.
  2. Check the pyx service status/health endpoint and retry once it is healthy.
  3. Inspect proxy/VPN interference: bypass the proxy for the API host or fix TLS interception, since intermediary error statuses surface here.
  4. If it persists, capture `uv login` with `-v` and the failing status code and contact the index operator.

Example fix

# before
uv login  # -> Failed to login with code `500 Internal Server Error`
# after
uv -v login https://pypi.???  # fresh session with verbose logging; complete browser flow immediately
Defensive patterns

Strategy: retry

Try / catch

match pyx_login_with_browser(&store, &client, &printer).await {
    Ok(token) => { /* proceed */ }
    Err(err) if err.to_string().contains("Failed to login with code") => {
        // transient server-side failure: fresh session, bounded retries
        for attempt in 0..3 {
            tokio::time::sleep(Duration::from_secs(5)).await;
            if let Ok(token) = pyx_login_with_browser(&store, &client, &printer).await {
                return Ok(token);
            }
            let _ = attempt;
        }
        Err(err)
    }
    Err(err) => Err(err),
}

Prevention

When it happens

Trigger: The pyx auth backend returns 500/502/503 while handling the status request (outage, bad gateway behind a proxy); the login session was invalidated server-side (expired or already consumed, returning 4xx); an intermediary (corporate proxy, captive portal) returns a non-404 error page status.

Common situations: Logging in from behind a corporate proxy that intercepts the API host; pyx service outage during CI authentication; retrying `uv login` with a stale browser tab that already completed the flow.

Related errors


AI-assisted analysis of astral-sh/uv@f1a42680ff (2026-08-16). Data as JSON: /api/errors/9cd36316c491254b. Report an issue: GitHub.