问题描述
开启分组的 claude_code_only 限制后,官方 Claude Code 客户端发出的部分请求会被误判为非 Claude Code 客户端,导致账号选择阶段失败:
this group only allows Claude Code clients
受影响的请求主要包括:
POST /v1/messages/count_tokens
- 部分
POST /v1/messages 且 stream=false 的请求
这些请求来自官方 Claude Code CLI,而不是第三方客户端。
环境信息
- Claude Code CLI:
2.1.156 (Claude Code)
- npm package:
@anthropic-ai/claude-code@2.1.156
- sub2api upstream main checked at:
f18451e56f15b31ef602ab238037b56c3522b19f
- 分组配置:
claude_code_only=true
- 模型示例:
claude-opus-4-8
已对比本地代码和 upstream main,以下关键文件/逻辑与 upstream main 一致,排除了本地 fork 修改导致的问题:
backend/internal/service/claude_code_validator.go
backend/internal/handler/gateway_helper.go
backend/internal/handler/gateway_handler.go
backend/internal/service/gateway_service.go 中 resolveGatewayGroup / checkClaudeCodeRestriction 相关片段
观察到的现象
在同一段 Claude Code 官方 CLI 会话中:
stream=true 的 /v1/messages 请求可以正常识别并转发
/v1/messages/count_tokens 请求会在账号选择前失败
- 部分
stream=false 的 /v1/messages 请求也会在账号选择前失败
- 服务端日志报错为
this group only allows Claude Code clients
失败发生在 sub2api 的账号选择阶段,因此这些失败请求没有被转发到上游 Anthropic。
代码路径分析
当前 ClaudeCodeValidator.Validate() 中的路径判断是:
path := r.URL.Path
if !strings.Contains(path, "messages") {
return true
}
因此 /v1/messages/count_tokens 会因为路径包含 messages 而进入 messages 严格校验逻辑。
同时 CountTokens() 中也会调用:
SetClaudeCodeClientContext(c, body, parsedReq)
而 SetClaudeCodeClientContext() 对包含 messages 的路径会继续调用 claudeCodeValidator.Validate(c.Request, bodyMap)。
如果官方 Claude Code 的 count_tokens 请求或部分内部 stream=false 请求不携带完整 messages 请求中的 system prompt / headers / metadata 形态,就会被判定为 IsClaudeCodeClient(ctx)=false,随后在 claude_code_only 分组中触发:
if !group.ClaudeCodeOnly || IsClaudeCodeClient(ctx) {
return group, ¤tID, nil
}
if group.FallbackGroupID == nil {
return nil, nil, ErrClaudeCodeOnly
}
期望行为
官方 Claude Code CLI 发出的辅助请求不应被 claude_code_only 误拦截,尤其是:
/v1/messages/count_tokens
- 官方 CLI 内部产生的
stream=false /v1/messages 请求
这些请求应该可以基于已确认的 Claude Code UA / CLI 请求特征通过,或至少不要因为缺少完整主请求 system prompt 而被当作非 Claude Code 客户端。
实际行为
开启 claude_code_only 后,上述官方 Claude Code 请求会被误判,导致返回 503,服务端日志中显示:
gateway.count_tokens_select_account_failed ... error=this group only allows Claude Code clients
gateway.select_account_no_available ... error=this group only allows Claude Code clients
可能的修复方向
建议考虑对 /v1/messages/count_tokens 单独处理,例如不要套用完整 /v1/messages 的 system prompt 严格校验,或者为官方 Claude Code 的 count_tokens / 内部辅助请求增加兼容分支。
对于 stream=false /v1/messages,可能也需要确认官方 Claude Code 在某些内部请求场景下是否不会携带完整主请求特征,避免误判。
补充说明
这个问题与本地 fork 修改无关:已将相关识别和分组限制代码与 upstream main 对比,关键逻辑一致。
相关历史问题看起来与此类似:#917、#1926、#1111、#248。
问题描述
开启分组的
claude_code_only限制后,官方 Claude Code 客户端发出的部分请求会被误判为非 Claude Code 客户端,导致账号选择阶段失败:受影响的请求主要包括:
POST /v1/messages/count_tokensPOST /v1/messages且stream=false的请求这些请求来自官方 Claude Code CLI,而不是第三方客户端。
环境信息
2.1.156 (Claude Code)@anthropic-ai/claude-code@2.1.156f18451e56f15b31ef602ab238037b56c3522b19fclaude_code_only=trueclaude-opus-4-8已对比本地代码和 upstream main,以下关键文件/逻辑与 upstream main 一致,排除了本地 fork 修改导致的问题:
backend/internal/service/claude_code_validator.gobackend/internal/handler/gateway_helper.gobackend/internal/handler/gateway_handler.gobackend/internal/service/gateway_service.go中resolveGatewayGroup/checkClaudeCodeRestriction相关片段观察到的现象
在同一段 Claude Code 官方 CLI 会话中:
stream=true的/v1/messages请求可以正常识别并转发/v1/messages/count_tokens请求会在账号选择前失败stream=false的/v1/messages请求也会在账号选择前失败this group only allows Claude Code clients失败发生在 sub2api 的账号选择阶段,因此这些失败请求没有被转发到上游 Anthropic。
代码路径分析
当前
ClaudeCodeValidator.Validate()中的路径判断是:因此
/v1/messages/count_tokens会因为路径包含messages而进入 messages 严格校验逻辑。同时
CountTokens()中也会调用:而
SetClaudeCodeClientContext()对包含messages的路径会继续调用claudeCodeValidator.Validate(c.Request, bodyMap)。如果官方 Claude Code 的
count_tokens请求或部分内部stream=false请求不携带完整 messages 请求中的 system prompt / headers / metadata 形态,就会被判定为IsClaudeCodeClient(ctx)=false,随后在claude_code_only分组中触发:期望行为
官方 Claude Code CLI 发出的辅助请求不应被
claude_code_only误拦截,尤其是:/v1/messages/count_tokensstream=false /v1/messages请求这些请求应该可以基于已确认的 Claude Code UA / CLI 请求特征通过,或至少不要因为缺少完整主请求 system prompt 而被当作非 Claude Code 客户端。
实际行为
开启
claude_code_only后,上述官方 Claude Code 请求会被误判,导致返回 503,服务端日志中显示:可能的修复方向
建议考虑对
/v1/messages/count_tokens单独处理,例如不要套用完整/v1/messages的 system prompt 严格校验,或者为官方 Claude Code 的 count_tokens / 内部辅助请求增加兼容分支。对于
stream=false /v1/messages,可能也需要确认官方 Claude Code 在某些内部请求场景下是否不会携带完整主请求特征,避免误判。补充说明
这个问题与本地 fork 修改无关:已将相关识别和分组限制代码与 upstream main 对比,关键逻辑一致。
相关历史问题看起来与此类似:#917、#1926、#1111、#248。