zed-industries/zed · error · RefreshError::Fatal

Token refresh failed (HTTP {}): {body}

Error message

Token refresh failed (HTTP {}): {body}

What it means

The refresh-token grant at OPENAI_TOKEN_URL returned a non-success HTTP status. The code path classifies transport failures as RefreshError::Transient, and this HTTP failure similarly means the refresh did not complete; a 400/401 usually means the refresh token itself is expired or revoked and re-authentication is required.

Source

Thrown at crates/openai_subscribed/src/openai_subscribed.rs:1255

) -> Result<CodexCredentials, RefreshError> {
    let body = form_urlencoded::Serializer::new(String::new())
        .append_pair("grant_type", "refresh_token")
        .append_pair("client_id", CLIENT_ID)
        .append_pair("refresh_token", refresh_token)
        .finish();

    let request = HttpRequest::builder()
        .method(Method::POST)
        .uri(OPENAI_TOKEN_URL)
        .header("Content-Type", "application/x-www-form-urlencoded")
        .body(AsyncBody::from(body))
        .map_err(|e| RefreshError::Transient(e.into()))?;

    let mut response = client
        .send(request)
        .await
        .map_err(|e| RefreshError::Transient(e))?;
    let status = response.status();
    let mut body = String::new();
    smol::io::AsyncReadExt::read_to_string(response.body_mut(), &mut body)
        .await
        .map_err(|e| RefreshError::Transient(e.into()))?;

    if !status.is_success() {
        let err = anyhow!("Token refresh failed (HTTP {}): {body}", status);
        // 400/401/403 indicate a revoked or invalid refresh token.
        // 5xx and other errors are treated as transient.
        if status == http_client::StatusCode::BAD_REQUEST
            || status == http_client::StatusCode::UNAUTHORIZED
            || status == http_client::StatusCode::FORBIDDEN
        {
            return Err(RefreshError::Fatal(err));
        }
        return Err(RefreshError::Transient(err));
    }

View on GitHub (pinned to 5a9b9558db)

Solutions

  1. If the body indicates an invalid_grant, sign out and complete a fresh interactive sign-in — refresh tokens are single-use or expired
  2. For 5xx or network-level statuses, retry the refresh after a delay
  3. Check the OpenAI status page for auth endpoint outages
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at crates/openai_subscribed/src/openai_subscribed.rs:1223 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of zed-industries/zed@5a9b9558db (2026-08-20). Data as JSON: /api/errors/0cd1b0ccdca4e5b0. Report an issue: GitHub.