feat: 适配claude的400错误码

This commit is contained in:
shaw
2025-10-11 13:00:02 +08:00
parent 4a925e2f8b
commit 9b211b063b

View File

@@ -38,6 +38,57 @@ class ClaudeRelayService {
return `此专属账号的Opus模型已达到周使用限制将于 ${formattedReset} 自动恢复,请尝试切换其他模型后再试。`
}
// 🧾 提取错误消息文本
_extractErrorMessage(body) {
if (!body) {
return ''
}
if (typeof body === 'string') {
const trimmed = body.trim()
if (!trimmed) {
return ''
}
try {
const parsed = JSON.parse(trimmed)
return this._extractErrorMessage(parsed)
} catch (error) {
return trimmed
}
}
if (typeof body === 'object') {
if (typeof body.error === 'string') {
return body.error
}
if (body.error && typeof body.error === 'object') {
if (typeof body.error.message === 'string') {
return body.error.message
}
if (typeof body.error.error === 'string') {
return body.error.error
}
}
if (typeof body.message === 'string') {
return body.message
}
}
return ''
}
// 🚫 检查是否为组织被禁用错误
_isOrganizationDisabledError(statusCode, body) {
if (statusCode !== 400) {
return false
}
const message = this._extractErrorMessage(body)
if (!message) {
return false
}
return message.toLowerCase().includes('this organization has been disabled')
}
// 🔍 判断是否是真实的 Claude Code 请求
isRealClaudeCodeRequest(requestBody) {
return ClaudeCodeValidator.hasClaudeCodeSystemPrompt(requestBody)
@@ -189,6 +240,10 @@ class ClaudeRelayService {
let isRateLimited = false
let rateLimitResetTimestamp = null
let dedicatedRateLimitMessage = null
const organizationDisabledError = this._isOrganizationDisabledError(
response.statusCode,
response.body
)
// 检查是否为401状态码未授权
if (response.statusCode === 401) {
@@ -221,6 +276,13 @@ class ClaudeRelayService {
)
await unifiedClaudeScheduler.markAccountBlocked(accountId, accountType, sessionHash)
}
// 检查是否返回组织被禁用错误400状态码
else if (organizationDisabledError) {
logger.error(
`🚫 Organization disabled error (400) detected for account ${accountId}, marking as blocked`
)
await unifiedClaudeScheduler.markAccountBlocked(accountId, accountType, sessionHash)
}
// 检查是否为529状态码服务过载
else if (response.statusCode === 529) {
logger.warn(`🚫 Overload error (529) detected for account ${accountId}`)
@@ -1253,6 +1315,25 @@ class ClaudeRelayService {
`❌ Claude API error response (Account: ${account?.name || accountId}):`,
errorData
)
if (this._isOrganizationDisabledError(res.statusCode, errorData)) {
;(async () => {
try {
logger.error(
`🚫 [Stream] Organization disabled error (400) detected for account ${accountId}, marking as blocked`
)
await unifiedClaudeScheduler.markAccountBlocked(
accountId,
accountType,
sessionHash
)
} catch (markError) {
logger.error(
`❌ [Stream] Failed to mark account ${accountId} as blocked after organization disabled error:`,
markError
)
}
})()
}
if (!responseStream.destroyed) {
// 发送错误事件
responseStream.write('event: error\n')