astral-sh/uv · error

Login session timed out after {STATUS_RETRY_LIMIT} seconds

Error message

Login session timed out after {STATUS_RETRY_LIMIT} seconds

What it means

The pyx browser login flow polls the status endpoint once per second and allows at most STATUS_RETRY_LIMIT (60) consecutive 404s before giving up with this timeout message. It means the login code was never completed in the browser within 60 seconds, so no OAuth tokens were ever returned.

Source

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

        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. Run `uv login` where a browser is available, copy the printed URL into a local browser if the remote box cannot open one, and finish authentication within 60 seconds.
  2. For headless/CI environments, avoid browser login entirely: use a pre-provisioned token (e.g., `uv login --token` or a keyring/text-store credential) instead.
  3. If SSO is slow, complete the identity-provider step in another tab first (warm session), then run `uv login` so approval is a single click inside the window.
  4. Simply re-run the command — each attempt generates a fresh login code.

Example fix

# before (headless CI)
uv login  # -> Login session timed out after 60 seconds
# after
UV_PYX_TOKEN=... uv sync  # or: uv login --token $PYX_TOKEN
Defensive patterns

Strategy: retry

Validate before calling

# Shell: guard headless environments before attempting browser login
if [ -z "${DISPLAY:-}" ] && [ -z "${WAYLAND_DISPLAY:-}" ] && [ ! -t 0 ]; then
  echo "no browser available; use: uv login --token $PYX_TOKEN" >&2
  exit 1
fi
uv login

Try / catch

match pyx_login_with_browser(&store, &client, &printer).await {
    Ok(token) => Ok(token),
    Err(err) if err.to_string().contains("timed out") => {
        // user simply didn't finish in 60s: one immediate retry with a fresh code
        pyx_login_with_browser(&store, &client, &printer).await
    }
    Err(err) => Err(err),
}

Prevention

When it happens

Trigger: Running `uv login` on a headless machine (CI container, SSH session) where `open::that` could not launch a browser or the user never visited the printed URL; starting login and getting distracted for over a minute; browser opened to the login URL but the user did not approve within 60 seconds.

Common situations: CI/automation scripts invoking `uv login` with no interactive browser; SSH into a remote box where xdg-open has no handler; slow SSO portal that takes longer than a minute to complete.

Understand the failure class

Related errors


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