jlcodes99/cockpit-tools · error

Authorization expired

Error message

Authorization expired

What it means

send_stream_request calls the Cloud Code streaming endpoint with an access_token; on HTTP 401 UNAUTHORIZED it returns the fixed error string 'Authorization expired'. This means the bearer token was rejected — it is missing, malformed, or no longer valid — and the code deliberately stops retrying since retrying with the same token cannot succeed.

Source

Thrown at src-tauri/src/modules/wakeup.rs:532

                                    if delay > 0 {
                                        crate::modules::logger::log_info(&format!(
                                            "[Wakeup] 准备重试: delay={}ms",
                                            delay
                                        ));
                                        sleep_with_cancel(
                                            std::time::Duration::from_millis(delay),
                                            cancel_rx,
                                        )
                                        .await?;
                                    }
                                    continue;
                                }
                            }
                        }
                    } else {
                        if status == reqwest::StatusCode::UNAUTHORIZED {
                            crate::modules::logger::log_error("[Wakeup] 授权失效 (401)");
                            return Err("Authorization expired".to_string());
                        }
                        if status == reqwest::StatusCode::FORBIDDEN {
                            crate::modules::logger::log_error("[Wakeup] 无权限 (403)");
                            return Err("Cloud Code access forbidden".to_string());
                        }
                        let text = await_with_cancel(cancel_rx, res.text())
                            .await?
                            .unwrap_or_default();
                        let retryable = status == reqwest::StatusCode::TOO_MANY_REQUESTS
                            || status.as_u16() >= 500;
                        let message = format!("唤醒请求失败: {} - {}", status, text);
                        last_error = Some(message.clone());
                        crate::modules::logger::log_warn(&format!(
                            "[Wakeup] 请求失败: url={}, status={}, retryable={}",
                            url, status, retryable
                        ));
                        if retryable && attempt < DEFAULT_ATTEMPTS {
                            let delay = get_backoff_delay_ms(attempt + 1);

View on GitHub (pinned to 1ed8b77992)

Solutions

  1. Trigger a token refresh (or re-authentication) before the next wakeup attempt
  2. Verify the access_token being attached is present and for the correct base URL/environment
  3. Have the user log in again if refresh_token is missing or also revoked
  4. Check device clock sync if tokens seem to expire instantly
  5. Inspect base_url order — a 401 from one mirror may be environment-specific

Example fix

// before
if status == reqwest::StatusCode::UNAUTHORIZED {
    return Err("Authorization expired".to_string());
}
// after
if status == reqwest::StatusCode::UNAUTHORIZED {
    if refresh_access_token().await.is_ok() {
        continue; // retry with new token
    }
    return Err("Authorization expired".to_string());
}
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight: ensure a token exists and refresh proactively if near expiry
if access_token.is_empty() || token_expires_in_secs() < 60 {
    refresh_access_token().await.expect("refresh failed; user must re-login");
}

Type guard

fn is_auth_expired(err: &str) -> bool { err == "Authorization expired" }

Try / catch

match trigger_wakeup_direct(...).await {
    Err(e) if e == "Authorization expired" => {
        if refresh_access_token().await.is_ok() {
            retry_once().await; // single retry with fresh token
        } else {
            prompt_relogin();
        }
    }
    other => handle(other),
}

Prevention

When it happens

Trigger: trigger_wakeup_direct → send_stream_request receives a 401 from the wakeup/stream API while carrying the stored access_token.

Common situations: Token expired after long idle; refresh flow failed silently or never ran; user logged out/revoked access server-side; token for the wrong environment (staging vs prod base URL); clock skew making a valid token appear expired.

Related errors


AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05). Data as JSON: /api/errors/50d1c01d658f05bf. Report an issue: GitHub.