mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-18 12:20:52 +08:00
fix(auth): 400 invalid_request_error 立即返回不再重试
当上游返回 400 Bad Request 且错误消息包含 invalid_request_error 时, 表示请求本身格式错误,切换账户不会改变结果。 修改: - 添加 isRequestInvalidError 判定函数 - 内层循环遇到此错误立即返回,不遍历其他账户 - 外层循环不再对此类错误进行重试
This commit is contained in:
@@ -607,6 +607,9 @@ func (m *Manager) executeMixedOnce(ctx context.Context, providers []string, req
|
|||||||
result.RetryAfter = ra
|
result.RetryAfter = ra
|
||||||
}
|
}
|
||||||
m.MarkResult(execCtx, result)
|
m.MarkResult(execCtx, result)
|
||||||
|
if isRequestInvalidError(errExec) {
|
||||||
|
return cliproxyexecutor.Response{}, errExec
|
||||||
|
}
|
||||||
lastErr = errExec
|
lastErr = errExec
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -660,6 +663,9 @@ func (m *Manager) executeCountMixedOnce(ctx context.Context, providers []string,
|
|||||||
result.RetryAfter = ra
|
result.RetryAfter = ra
|
||||||
}
|
}
|
||||||
m.MarkResult(execCtx, result)
|
m.MarkResult(execCtx, result)
|
||||||
|
if isRequestInvalidError(errExec) {
|
||||||
|
return cliproxyexecutor.Response{}, errExec
|
||||||
|
}
|
||||||
lastErr = errExec
|
lastErr = errExec
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -711,6 +717,9 @@ func (m *Manager) executeStreamMixedOnce(ctx context.Context, providers []string
|
|||||||
result := Result{AuthID: auth.ID, Provider: provider, Model: routeModel, Success: false, Error: rerr}
|
result := Result{AuthID: auth.ID, Provider: provider, Model: routeModel, Success: false, Error: rerr}
|
||||||
result.RetryAfter = retryAfterFromError(errStream)
|
result.RetryAfter = retryAfterFromError(errStream)
|
||||||
m.MarkResult(execCtx, result)
|
m.MarkResult(execCtx, result)
|
||||||
|
if isRequestInvalidError(errStream) {
|
||||||
|
return nil, errStream
|
||||||
|
}
|
||||||
lastErr = errStream
|
lastErr = errStream
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -1110,6 +1119,9 @@ func (m *Manager) shouldRetryAfterError(err error, attempt int, providers []stri
|
|||||||
if status := statusCodeFromError(err); status == http.StatusOK {
|
if status := statusCodeFromError(err); status == http.StatusOK {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
if isRequestInvalidError(err) {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
wait, found := m.closestCooldownWait(providers, model, attempt)
|
wait, found := m.closestCooldownWait(providers, model, attempt)
|
||||||
if !found || wait > maxWait {
|
if !found || wait > maxWait {
|
||||||
return 0, false
|
return 0, false
|
||||||
@@ -1430,6 +1442,21 @@ func statusCodeFromResult(err *Error) int {
|
|||||||
return err.StatusCode()
|
return err.StatusCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isRequestInvalidError returns true if the error represents a client request
|
||||||
|
// error that should not be retried. Specifically, it checks for 400 Bad Request
|
||||||
|
// with "invalid_request_error" in the message, indicating the request itself is
|
||||||
|
// malformed and switching to a different auth will not help.
|
||||||
|
func isRequestInvalidError(err error) bool {
|
||||||
|
if err == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
status := statusCodeFromError(err)
|
||||||
|
if status != http.StatusBadRequest {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return strings.Contains(err.Error(), "invalid_request_error")
|
||||||
|
}
|
||||||
|
|
||||||
func applyAuthFailureState(auth *Auth, resultErr *Error, retryAfter *time.Duration, now time.Time) {
|
func applyAuthFailureState(auth *Auth, resultErr *Error, retryAfter *time.Duration, now time.Time) {
|
||||||
if auth == nil {
|
if auth == nil {
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user