fix(openai): treat 401 {"detail":"Unauthorized"} as permanent auth failure
- ratelimit_service: detect non-standard OpenAI 401 format and permanently disable account - account_test_service: mark account error on 401 during connection test Made-with: Cursor
This commit is contained in:
@@ -551,6 +551,11 @@ func (s *AccountTestService) testOpenAIAccountConnection(c *gin.Context, account
|
||||
account.RateLimitResetAt = resetAt
|
||||
}
|
||||
}
|
||||
// 401 Unauthorized: 标记账号为永久错误
|
||||
if resp.StatusCode == http.StatusUnauthorized && s.accountRepo != nil {
|
||||
errMsg := fmt.Sprintf("Authentication failed (401): %s", string(body))
|
||||
_ = s.accountRepo.SetError(ctx, account.ID, errMsg)
|
||||
}
|
||||
return s.sendErrorAndEnd(c, fmt.Sprintf("API returned %d: %s", resp.StatusCode, string(body)))
|
||||
}
|
||||
|
||||
|
||||
@@ -161,6 +161,16 @@ func (s *RateLimitService) HandleUpstreamError(ctx context.Context, account *Acc
|
||||
shouldDisable = true
|
||||
break
|
||||
}
|
||||
// OpenAI: {"detail":"Unauthorized"} 表示 token 完全无效(非标准 OpenAI 错误格式),直接标记 error
|
||||
if account.Platform == PlatformOpenAI && gjson.GetBytes(responseBody, "detail").String() == "Unauthorized" {
|
||||
msg := "Unauthorized (401): account authentication failed permanently"
|
||||
if upstreamMsg != "" {
|
||||
msg = "Unauthorized (401): " + upstreamMsg
|
||||
}
|
||||
s.handleAuthError(ctx, account, msg)
|
||||
shouldDisable = true
|
||||
break
|
||||
}
|
||||
// OAuth 账号在 401 错误时临时不可调度(给 token 刷新窗口);非 OAuth 账号保持原有 SetError 行为。
|
||||
// Antigravity 除外:其 401 由 applyErrorPolicy 的 temp_unschedulable_rules 自行控制。
|
||||
if account.Type == AccountTypeOAuth && account.Platform != PlatformAntigravity {
|
||||
|
||||
Reference in New Issue
Block a user