ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Claude 报错 Extra inputs are not permitted:代理剥离 Beta 标头的排查与修复

Claude 报错 Extra inputs are not permitted:代理剥离 Beta 标头的排查与修复 1. 先搞清楚这个 400 到底在报什么Extra inputs are not permitted这个报错字面意思是「不允许出现额外输入」它跟你的 API Key 有没有余额、模型名写没写对基本没关系。它出现的位置很固定请求已经打到 Anthropic 侧或 Bedrock 侧服务端在解析请求体时发现了它不认识的字段于是直接 400 拒绝。真正让人困惑的地方在于同样的 Claude Code、同样的配置直连的时候一切正常一旦中间加了一层代理、网关或者中转服务就开始报这个错。很多人第一反应是去改模型名、换 Key、降版本折腾一圈发现没用因为问题根本不在这些地方。这个报错的核心检索词就是 Claude、Extra inputs are not permitted、代理、Beta 标头。它适合谁看适合所有用 Claude Code 或自己写脚本调 Anthropic API、并且请求链路里存在一层转发的人。典型触发场景是你用了 LiteLLM、Nginx 反代、OpenRouter 这类网关或者后端接的是 AWS Bedrock、Vertex AI然后 Claude Code 版本又比较新2.1.22 之后引入了实验性 Beta 功能。一句话概括成因Claude Code 在请求体里塞了 Beta 字段比如defer_loading、context_management同时在请求头里用anthropic-beta声明「这些字段是我主动开启的实验特性请放行」。代理把请求头剥掉了但请求体原样转发服务端看到一堆没人声明的陌生字段就判定为非法输入。下面从请求头透传的角度把定位和修复一步步拆开。2. 前置准备用 TaoToken 打通调用链路在动手排查之前先把调用链路固定下来避免一边查标头一边还在怀疑 Key 和地址。我这边统一用 TaoToken 作为接入层它的好处是地址和 Key 管理集中出问题时能快速区分「是链路问题还是标头问题」。官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 这个地址不加 UTM 参数直接填进配置即可。你需要先拿到一个可用的 Key。进入控制台创建https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 然后在 API Keys 页面生成密钥https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 。生成后先复制保存页面刷新后就不再完整显示。如果你只是想先确认模型本身能不能通可以打开模型对话页发一条消息试试https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。这一步的意义是建立一个「基线」——如果对话页正常、Claude Code 报 400那问题几乎可以锁定在 Claude Code 发出的请求头/请求体上而不是账号或网络。接入文档在这里配置字段和参数说明以它为准https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。把 Key 和 Base URL 准备好之后再进入下面的配置环节。3. 可复制配置让 Beta 标头正确透传修复思路只有两条要么让代理正确转发anthropic-beta标头要么让 Claude Code 干脆别发这些 Beta 字段。先讲透传方案再讲禁用方案你可以按自己是否需要 Beta 功能来选。3.1 先确认 Claude Code 侧发了什么在改代理之前先让 Claude Code 把请求头打出来确认它确实发了anthropic-beta。设置调试环境变量后启动export CLAUDE_CODE_DEBUG1 claude日志里会看到请求头部分重点找anthropic-beta这一行正常应该类似anthropic-beta: prompt-caching-scope-2026-01-05,defer-loading-2026-03-15如果这里就没有那问题在 Claude Code 配置如果有但代理侧收不到问题就在代理。这一步是分水岭别跳过。3.2 Nginx 反向代理的标头透传配置Nginx 默认不会转发所有自定义标头anthropic-beta这种非标准头很容易被丢掉。需要在 location 块里显式声明转发server { listen 443 ssl; server_name your-proxy.example.com; location /v1/ { proxy_pass https://api.anthropic.com/v1/; # 关键允许并转发 anthropic-beta 标头 proxy_pass_header anthropic-beta; proxy_set_header anthropic-beta $http_anthropic_beta; proxy_set_header Host api.anthropic.com; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 流式响应必须关掉缓冲否则 SSE 会被截断 proxy_buffering off; proxy_cache off; proxy_read_timeout 300s; } }proxy_pass_header和proxy_set_header这两行是核心。前者告诉 Nginx 这个头允许通过后者把客户端发来的值原样传给上游。改完执行nginx -t校验语法再nginx -s reload生效。3.3 LiteLLM 网关的两种处理方式如果你用的是 LiteLLM它默认对 Anthropic 原生 API 是会转发anthropic-beta的但接 Bedrock 时 Bedrock 本身不支持这些字段所以更推荐直接丢弃不支持的参数model_list: - model_name: claude-sonnet litellm_params: model: bedrock/us.anthropic.claude-sonnet-4-20250514 drop_params: true additional_drop_params: [defer_loading, context_management]drop_params: true让 LiteLLM 自动过滤后端不认识的参数additional_drop_params再精确点名几个已知会惹事的字段。这样即使 Claude Code 以后新增 Beta 字段也不会因为后端不支持而 400。3.4 最省事的兜底禁用实验性 Beta如果你不需要 Tool Search、上下文自动裁剪这些实验特性最直接的办法是让 Claude Code 不发 Beta 字段。设置环境变量export CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS1想永久生效就写进 shell 配置echo export CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS1 ~/.zshrc source ~/.zshrc或者在~/.claude/settings.json里配置{ env: { CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS: 1 } }设置后 Claude Code 会自动剥离 Beta 请求头、移除工具 schema 里的defer_loading、清掉请求体里的context_management标准字段全部保留。大多数情况下这个错误会立刻消失。4. 验证请求确认标头完整到达改完配置不能只看「不报错了」要确认标头是真的透传过去了。下面给几个可操作的检查动作。4.1 用最小请求验证标头先绕开 Claude Code用 curl 直接打一个带anthropic-beta的最小请求确认链路本身能透传curl -sS https://taotoken.net/api/v1/messages \ -H x-api-key: $ANTHROPIC_API_KEY \ -H anthropic-version: 2023-06-01 \ -H anthropic-beta: prompt-caching-scope-2026-01-05 \ -H content-type: application/json \ -d { model: claude-sonnet-4-20250514, max_tokens: 64, messages: [{role: user, content: ping}] }如果返回正常内容说明标头能到达如果返回 400 且提到Extra inputs are not permitted说明标头在中间被剥了。这一步能把「链路问题」和「Claude Code 问题」彻底分开。4.2 在代理侧抓包确认在代理服务器上抓一下 443 端口的流量过滤anthropic-betasudo tcpdump -i any -A -s 0 tcp port 443 | grep -i anthropic-beta如果抓不到这个头说明客户端到代理这一段就丢了如果抓到了但上游还报错说明代理到上游这一段丢了。Nginx 也可以在 location 里加临时日志access_log /var/log/nginx/anthropic_debug.log; log_format anthropic_debug $http_anthropic_beta;4.3 回归检查清单修复后按这个清单过一遍确认没有副作用检查项预期结果基本对话正常响应无 400MCP 工具调用工具可正常连接和调用流式响应输出完整无中途截断/doctor诊断所有检查项通过/usage查询用量信息正常显示流式响应这一项特别容易被忽略。proxy_buffering off没配的话标头问题解决了SSE 又会被缓冲截断表现是回复到一半卡住。5. 本篇常见错排查报错依旧但日志里标头明明在。这种情况多半是后端本身不支持这些字段比如 Bedrock 和 Vertex AI 的 API 规范里就没有defer_loading。标头传得再对也没用得走drop_params或禁用 Beta 的路线。改了 Nginx 配置没生效。先nginx -t看语法再确认 reload 成功。还有一种情况是配置写在了错误的 server 块里请求实际走的是另一个 location标头自然没被处理。CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS设了没用。检查是不是设在了当前 shell 之外或者被settings.json里的其他 env 覆盖了。用echo $CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS确认当前会话真的读到了。升级 Claude Code 后又复发。新版本可能引入新的 Beta 字段。升级后先跑/doctor如果出现新的 400确认是不是新字段导致然后更新代理的additional_drop_params列表。OpenRouter 这类网关怎么都传不过去。部分第三方网关对自定义标头支持有限这种情况别硬刚直接用禁用 Beta 的方案或者换成能透传标头的接入方式。6. 后续怎么调更顺手排查完这一轮建议把「代理层统一参数清洗」当成默认动作。在 LiteLLM 里常驻drop_params: true加additional_drop_params这样 Claude Code 以后新增什么实验字段都不会再触发同类 400。如果你长期用 Claude Code 做编码和 Agent 任务可以考虑走 Coding Plan把调用配额和模型切换集中管理省得每次都在环境变量上折腾https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。需要自己写脚本或接第三方工具时Key 还是从 API Keys 页面拿https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 字段含义对照接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。最后留一个我踩过的坑标头透传和请求体字段清洗是两件事别只改一个。代理转发了anthropic-beta但后端是 Bedrock照样 400反过来只清洗字段不禁标头Anthropic 原生 API 那边可能又因为标头声明了不存在的字段而报错。两边对齐问题才算真正闭环。
返回列表