jlcodes99/cockpit-tools · error
Cloud Code access forbidden
Error message
Cloud Code access forbidden
What it means
In send_stream_request, an HTTP 403 FORBIDDEN from the Cloud Code endpoint is converted into the error string 'Cloud Code access forbidden'. Unlike 401 (authentication), 403 means the server recognized the caller but denies permission for this operation or resource, so retrying with the same credentials will not help.
Source
Thrown at src-tauri/src/modules/wakeup.rs:536
));
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);
if delay > 0 {
crate::modules::logger::log_info(&format!(
"[Wakeup] 准备重试: delay={}ms",
delayView on GitHub (pinned to 1ed8b77992)
Solutions
- Confirm the account has Cloud Code permission enabled (plan/admin settings)
- Re-authenticate so the token includes required scopes
- Check workspace/organization membership and any IP or region restrictions
- Ask the service admin to unblock the client if a policy/allowlist is in effect
- Distinguish 403 from 401 in client handling — do not retry with the same token
Example fix
// before
if status == reqwest::StatusCode::FORBIDDEN {
return Err("Cloud Code access forbidden".to_string());
}
// after
if status == reqwest::StatusCode::FORBIDDEN {
return Err(format!("Cloud Code access forbidden (account lacks permission; check plan/scopes for base {})", base));
} Defensive patterns
Strategy: fallback
Validate before calling
// Pre-flight permission check via a cheap authenticated endpoint before wakeup
let me = client.get(format!("{base}/me")).bearer_auth(token).send().await?;
if me.status() == reqwest::StatusCode::FORBIDDEN {
eprintln!("account lacks Cloud Code permission; aborting wakeup");
} Type guard
fn is_access_forbidden(err: &str) -> bool { err == "Cloud Code access forbidden" } Try / catch
match trigger_wakeup_direct(...).await {
Err(e) if e == "Cloud Code access forbidden" => {
// do NOT retry with same token; disable wakeup and surface a permission message
disable_wakeup_with_reason("Cloud Code access denied for this account");
}
other => handle(other),
} Prevention
- Check plan/admin permissions once at login, not on every wakeup
- Request all required scopes at authorization time
- Never treat 403 as retryable — alert the user instead
- Keep workspace/organization membership and IP allowlists up to date
When it happens
Trigger: trigger_wakeup_direct → send_stream_request gets a 403 response while calling the wakeup/stream API with a valid but insufficiently-privileged access_token.
Common situations: Account/plan lacks the Cloud Code feature; admin disabled the integration; token scopes too narrow; IP/region or workspace allowlist blocks the client; user was removed from the required team/organization.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Claude OAuth start 响应缺少关键字段
- Qoder OAuth 授权链接为空
- [WebDAV] Auto backup upload failed
- [TraeAutoCheckin] 账号 ${account.id} 签到异常:
- [TraeAutoCheckin] 刷新账号列表失败:
AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05).
Data as JSON: /api/errors/5818fbfe4de5131f.
Report an issue: GitHub.