1. 从报错信息反推 Codex 配置体系
1.1 为什么 401 报错总是绕不开 config.toml 和 auth.json
Codex 这类命令行 AI 编程工具,配置体系其实就两个核心文件在撑着:一个是config.toml,管的是模型选择、MCP 服务、代理路由这些"行为层"的东西;另一个是auth.json,管的是 API Key、Token 这类"身份层"的东西。很多人一看到 401 就慌了,觉得是不是账号被封了、是不是服务挂了,其实绝大多数情况下,问题就出在这两个文件的配合上。
我先把 401 的本质说清楚。HTTP 401 的意思是"未授权",翻译成人话就是:服务器收到了你的请求,但它不认你提供的身份凭证。注意,它不是说"你没权限",那是 403。401 是"我根本不知道你是谁"。所以当你看到unexpected status 401 unauthorized: incorrect api key provided: sk-svcac****这种报错时,核心信息就一个——你递过去的 Key,服务端不认。
那为什么会出现"不认"的情况?常见的有这么几类:Key 本身写错了(复制粘贴时多了空格、少了字符)、Key 和当前请求的端点不匹配(比如拿 A 平台的 Key 去请求 B 平台的接口)、Key 已经过期或被撤销、auth.json里的凭证和config.toml里配置的 provider 对不上。这四类里,第四类是最隐蔽的,也是最多人踩坑的地方。
我见过太多人,config.toml里写着用某个 provider,auth.json里却放着另一个平台的 Key,然后跑起来就 401,还一脸懵。这两个文件是联动的,不是各管各的。config.toml决定"走哪条路",auth.json决定"拿什么通行证",路和证必须匹配。
1.2 config.toml 与 auth.json 的职责边界
为了让大家彻底搞清楚,我做个类比。把 Codex 想象成你要去一个会员制健身房锻炼。config.toml就是你填的入会申请表,上面写着你打算用哪个分店(provider)、练什么项目(model)、要不要请私教(MCP 服务)。auth.json就是你的会员卡,里面存着你的身份信息。
你拿着 A 店的会员卡去 B 店刷,前台当然不认,这就是 401。你申请表上写的是要去 B 店,但卡是 A 店的,系统一核对,对不上,也是 401。所以排查 401 的第一步,永远是先确认这两个文件描述的是不是同一个"店"。
具体到文件内容,config.toml里通常会有类似这样的结构:
model = "gpt-5.6-sol" model_provider = "openai" [model_providers.openai] name = "OpenAI" base_url = "https://api.openai.com/v1" env_key = "OPENAI_API_KEY"而auth.json里则是:
{ "OPENAI_API_KEY": "sk-xxxxxxxxxxxxxxxx" }注意这里的env_key字段,它是个"指针",指向auth.json里对应的 Key 名。如果config.toml里写的是env_key = "OPENAI_API_KEY",但auth.json里存的键名是openai_key或者别的什么,那 Codex 就找不到对应的凭证,自然就 401 了。这个细节极其容易被忽略,因为两个文件分开看都没毛病,合起来才出问题。
1.3 那些"配置不生效"的报错到底在说什么
热词里有一条特别典型:codex is ignoring 1 unrecognized configuration setting. check for typos or deprecated settings. user (c:\users\丁子洋.codex\config.toml): mcp_servers.node_repl.type is ignored.
这条报错的意思是:Codex 读到了你的config.toml,但里面有个配置项它不认识,所以直接忽略了。注意关键词"ignored"——它不是报错崩溃,而是"我看到了,但我不认,跳过"。这种情况下,你以为自己配了某个功能,实际上根本没生效,因为那一行被静默跳过了。
为什么会"不认识"?两种可能:一是拼写错误,比如把mcp_servers写成了mcp_server,或者type写成了types;二是版本不匹配,你用的配置语法是旧版本的,新版本已经废弃了,或者反过来,你抄了个新版本的配置,但本地装的是老版本 Codex。
这里有个很实用的排查习惯:每次改完config.toml,不要急着跑任务,先跑一个最简单的命令,看看有没有 "unrecognized configuration setting" 的警告。有警告就先解决警告,别带着警告往下跑,否则后面出的问题你根本分不清是配置没生效还是逻辑本身有问题。
2. 401 报错的分类排查与逐项击破
2.1 Key 格式类 401:从 sk-svcac 说起
热词里反复出现incorrect api key provided: sk-svcac****和incorrect api key provided: sk-,这两个其实是同一类问题的不同表现。sk-svcac开头的 Key 通常是某些平台的服务账号 Key,而sk-后面直接截断的,往往是 Key 压根没填完整。
先说 Key 格式。不同平台的 Key 前缀不一样,OpenAI 官方的是sk-开头,OpenRouter 的是sk-or-开头,有些第三方聚合平台会用sk-svcac这种前缀。你拿什么前缀的 Key,就得配对应平台的base_url。这是铁律。
我整理了一个常见平台的对照表,方便大家核对:
| 平台类型 | Key 前缀特征 | 对应 base_url 特征 |
|---|---|---|
| OpenAI 官方 | sk- | api.openai.com |
| OpenRouter | sk-or- | openrouter.ai/api |
| 第三方聚合 | sk-svcac / sk-xxx | 各平台自有域名 |
| 自建服务 | 自定义 | 本地或内网地址 |
排查动作很简单:打开auth.json,把 Key 完整复制出来,数一下长度,看看前缀,然后打开config.toml,核对base_url是不是这个 Key 所属平台的地址。两个对不上,改到对上为止。
还有一个高频坑:Key 末尾带了换行符或者空格。从网页复制 Key 的时候,很容易把末尾的空白字符一起复制进去。这种 Key 在肉眼看来完全正常,但程序读进去就多了个\n,服务端一比对,不匹配,401。解决办法是用编辑器打开auth.json,把光标移到 Key 末尾,看看有没有多余的空格或换行,有就删掉。
2.2 凭证缺失类 401:missing bearer 与 auth token unavailable
热词里有unexpected status 401 unauthorized: missing bearer or basic authentication和codex auth token is unavailable,这两条说的是同一件事:请求发出去了,但压根没带身份凭证。
missing bearer的意思是,HTTP 请求头里应该有个Authorization: Bearer xxx的字段,但实际发出去的请求里没有这个字段。为什么会没有?因为 Codex 在auth.json里没找到对应的 Key,或者找到了但没成功注入到请求头里。
auth token is unavailable更直接,就是"令牌不可用"。这种情况通常发生在:auth.json文件不存在、文件存在但是空的、文件里的 Key 名和config.toml里env_key指定的名字对不上。
排查顺序我建议这样走:
- 确认
auth.json文件存在,路径正确。Windows 下默认在C:\Users\你的用户名\.codex\auth.json,Mac/Linux 下在~/.codex/auth.json。 - 确认文件内容不是空的,且是合法的 JSON 格式。JSON 格式错误会导致整个文件读取失败,表现就是"token unavailable"。
- 确认
auth.json里的键名,和config.toml里env_key的值完全一致,大小写敏感。 - 确认 Key 的值没有多余空白字符。
这四步走完,missing bearer和auth token is unavailable基本都能解决。我遇到过最离谱的一次,是用户把auth.json存成了auth.json.txt,Windows 默认隐藏扩展名,他看文件名是auth.json,实际是auth.json.txt,Codex 当然读不到。所以如果你在 Windows 上排查,先把"显示文件扩展名"打开,这个习惯能省你很多时间。
2.3 代理路由类 401:cc switch local proxy failed 的真相
热词里有一条特别长:unexpected status 401 unauthorized: cc switch local proxy failed while handling codex endpoint /responses。这条报错信息量很大,拆开看:cc switch是某个配置切换工具,local proxy说明它起了个本地代理,failed while handling codex endpoint /responses说明是在处理 Codex 的/responses端点时失败的。
这类问题的本质是:你用了第三方工具来管理 Codex 的配置切换,这个工具在本地起了一个代理,Codex 的请求先发给本地代理,代理再转发给真正的服务端。401 出现在这个链路里,可能是代理转发时把凭证弄丢了,也可能是代理配置的目标端点和凭证不匹配。
排查这类问题,我的建议是"先绕过代理,直连测试"。具体做法:临时把config.toml里的base_url改成官方地址,auth.json里放官方 Key,直接跑一次。如果直连能通,说明问题出在代理工具上;如果直连也 401,说明是 Key 或配置本身的问题,跟代理无关。
这个"二分法"排查思路非常管用。任何涉及中间层的报错,第一步都是把中间层拿掉,看问题还在不在。在,说明是底层问题;不在,说明是中间层问题。这样能快速缩小排查范围,避免在错误的方向上浪费时间。
2.4 模型不支持类报错:gpt-5.6-sol is not supported
热词里有一条:{"detail":"the 'gpt-5.6-sol' model is not supported when using codex with a..."}。这条虽然不是 401,但经常和 401 混在一起出现,因为很多人配 Key 的时候顺手把模型名也改了,结果 Key 对了但模型名不对,报错信息看起来又像是权限问题。
模型不支持的报错,核心原因是config.toml里model字段填的模型名,当前 provider 不支持。每个 provider 支持的模型列表是固定的,你填了个它没有的模型,它就报错。
解决办法:去对应 provider 的文档里查支持的模型列表,把model字段改成列表里有的。别凭记忆填,别抄别人的配置,因为不同账号、不同套餐支持的模型可能不一样。
这里有个经验:如果你不确定该填什么模型,先填一个最通用的,比如gpt-4o或者 provider 文档里标注为"默认"的那个。跑通了再换成你想要的。先求通,再求好,这个顺序不能反。
3. 配置不生效的深层原因与修复实操
3.1 配置文件路径与加载顺序的坑
Codex 读配置文件是有优先级的。一般来说,项目目录下的配置会覆盖用户目录下的全局配置。也就是说,如果你在项目根目录放了一个.codex/config.toml,它会覆盖C:\Users\你的用户名\.codex\config.toml。
这个机制本身是合理的,但很多人不知道,于是在全局配置里改了半天,发现不生效,因为项目目录下有个旧的配置文件在"压着"它。排查方法:在项目根目录搜一下有没有.codex文件夹,有的话看看里面的配置是不是你想要的。
还有一种情况是环境变量覆盖。有些配置项可以通过环境变量设置,环境变量的优先级通常高于配置文件。如果你在系统里设了个OPENAI_API_KEY的环境变量,但auth.json里放的是另一个 Key,那实际生效的是环境变量里的那个。这种"隐形覆盖"最难排查,因为你在文件里怎么看都是对的。
我的习惯是:排查配置问题时,先把所有相关的环境变量列出来看一眼。Windows 下用set | findstr OPENAI,Mac/Linux 下用env | grep OPENAI。确认没有意外的环境变量在捣乱,再去改文件。
3.2 TOML 语法错误的隐蔽表现
config.toml是 TOML 格式,这个格式对语法要求比较严格。常见的语法错误包括:字符串没加引号、布尔值写成了True而不是true、表格(table)的层级写错了、重复定义了同一个键。
TOML 语法错误的表现往往不是直接报"语法错误",而是"某个配置项被忽略"或者"配置读取失败"。比如热词里那条mcp_servers.node_repl.type is ignored,很可能就是mcp_servers下面的层级结构写错了,导致type这个键没被正确识别。
排查 TOML 语法,我推荐用在线 TOML 校验工具,把config.toml的内容贴进去,它会告诉你哪一行有问题。或者用 VS Code 装个 TOML 插件,语法错误会直接标红。别靠肉眼找,TOML 的缩进和层级用肉眼很容易看漏。
这里补充一个细节:TOML 里的表格定义,[model_providers.openai]这种写法,方括号里的路径是用点分隔的。如果你写成了[model_providers]然后下面再写[openai],那是两个不同的表格,层级关系就错了。这种错误很隐蔽,因为两种写法看起来都"像那么回事"。
3.3 配置修改后的验证流程
改完配置不要直接跑正式任务,先做验证。我总结了一个三步验证法:
第一步,跑一个最简单的命令,比如让 Codex 输出一句"hello",看能不能通。这一步验证的是"身份认证"和"基础连通性"。
第二步,跑一个需要调用模型的任务,比如让它解释一段代码。这一步验证的是"模型配置"是否正确。
第三步,跑一个需要用到 MCP 服务的任务,比如让它调用某个工具。这一步验证的是"MCP 配置"是否生效。
三步都过了,说明配置没问题。哪一步卡住了,就针对那一步排查。这个流程的好处是把问题隔离了,不会出现"一堆配置改完,不知道哪个有问题"的情况。
提示:每次只改一个配置项,改完就验证。一次性改多个配置项,出问题了你根本不知道是哪个改坏的。这是排查配置问题的黄金法则。
4. 高频问题速查与避坑经验
4.1 常见报错速查表
我把热词里出现的高频报错整理成了一张速查表,方便大家对号入座:
| 报错关键词 | 根本原因 | 首选排查动作 |
|---|---|---|
| incorrect api key provided | Key 错误或与端点不匹配 | 核对 Key 前缀与 base_url |
| missing bearer | 请求未携带凭证 | 检查 auth.json 是否存在且键名匹配 |
| auth token is unavailable | 凭证文件缺失或格式错误 | 检查文件路径与 JSON 合法性 |
| cc switch local proxy failed | 代理层转发异常 | 绕过代理直连测试 |
| unrecognized configuration setting | 配置项拼写错误或版本不匹配 | 校验 TOML 语法与版本兼容性 |
| model is not supported | 模型名不在 provider 支持列表 | 查文档改用支持的模型名 |
| no api key for provider route | provider 路由未配置 Key | 检查 config.toml 的 provider 段 |
这张表建议存下来,下次遇到报错先查表,能省不少时间。
4.2 我踩过的三个真实坑
第一个坑:Key 复制时带了不可见字符。有一次我配 OpenRouter 的 Key,怎么弄都 401,反复核对 Key 内容都对。最后用十六进制编辑器打开auth.json,发现 Key 末尾有个0x0A(换行符)。删掉就好了。这个坑的教训是:从网页复制 Key 后,粘贴到编辑器里,手动把光标移到末尾按一下 Delete,确保没有隐藏字符。
第二个坑:config.toml里env_key和auth.json里的键名大小写不一致。我写的是OPENAI_API_KEY,auth.json里存的是openai_api_key。看起来差不多,但程序是大小写敏感的,就是找不到。这个坑的教训是:键名统一用大写加下划线,两个文件里保持完全一致。
第三个坑:项目目录下的旧配置覆盖了全局配置。我在全局配置里改了半天没生效,最后发现项目根目录有个.codex/config.toml是几个月前建的,一直在生效。这个坑的教训是:排查配置问题前,先确认当前生效的是哪个配置文件。
4.3 配置管理的长期习惯
配置这东西,改一次两次还好,改多了就容易乱。我现在的习惯是:所有配置文件用 Git 管理,每次改动都提交,写清楚改了什么、为什么改。这样出问题可以回滚,也能看到历史变更。
另外,auth.json里存的是敏感凭证,不要提交到公开仓库。我的做法是auth.json加进.gitignore,然后建一个auth.json.example模板文件提交上去,模板里只写键名不写值。这样既能让别人知道需要配哪些 Key,又不会泄露真实凭证。
还有个小技巧:给config.toml里的关键配置项加注释。TOML 支持#注释。比如在base_url上面写一行# 这是 OpenRouter 的端点,换平台时记得同步改 auth.json。注释不占运行开销,但能在你几个月后回头看时救命。
4.4 关于"国内能否使用"的客观说明
热词里有"codex国内能用吗"、"国内如何使用codex"这类问题。这里我只说技术层面的事实:Codex 作为工具本身,能否连通取决于你配置的base_url指向的服务是否可达。如果你配置的是官方端点,那连通性取决于网络环境;如果你配置的是第三方聚合平台的端点,那取决于该平台的服务状态。
从排查角度,如果你遇到的是连接超时而不是 401,那说明请求根本没到达服务端,问题在网络层而不是认证层。这种情况下,先确认base_url能不能 ping 通,再确认端口是否开放。401 是"到了但不认",超时是"根本没到",两者排查方向完全不同,别混为一谈。
5. 从 401 排查延伸出的配置健壮性思考
5.1 为什么建议用环境变量管理敏感信息
把 Key 直接写在auth.json里,虽然方便,但有个隐患:文件一旦泄露,Key 就暴露了。更稳妥的做法是用环境变量。config.toml里的env_key字段,本质上就是让你指定"从哪个环境变量读 Key"。
具体操作:在系统里设置环境变量OPENAI_API_KEY,值为你的 Key。然后config.toml里写env_key = "OPENAI_API_KEY"。这样auth.json里就不需要存真实 Key 了,甚至可以不放这个文件。环境变量的好处是,它不会跟着代码仓库走,泄露风险更低。
当然,环境变量也有它的坑:设置完要重启终端才生效,而且不同 shell 的设置方式不一样。Windows 的 PowerShell 用$env:OPENAI_API_KEY="sk-xxx",CMD 用set OPENAI_API_KEY=sk-xxx,Mac/Linux 的 bash 用export OPENAI_API_KEY="sk-xxx"。设置完用echo命令确认一下值对不对,别设了个空值自己还不知道。
5.2 多 provider 配置的隔离策略
如果你同时用多个 provider,比如官方一个、聚合平台一个,那配置管理就更要讲究隔离。我的做法是:每个 provider 单独一个配置文件,用的时候通过工具切换,而不是把所有 provider 都塞进一个config.toml里。
塞在一起的问题是,model_provider字段只能指向一个 provider,你切来切去容易切错。而且不同 provider 的env_key不一样,混在一起容易搞混。分开管理,每个文件职责单一,切换时整体替换,出错概率低很多。
如果非要用一个文件管理多个 provider,那至少把每个 provider 的配置段用注释分隔清楚,并且在文件顶部写一行当前激活的是哪个 provider。这样你打开文件一眼就能看到当前状态,不用去翻model_provider字段。
5.3 配置变更的记录与回滚
配置出问题的时候,最怕的就是"不知道改了什么"。我现在的做法是,每次改配置前,先把当前配置文件复制一份,命名为config.toml.bak.日期。改坏了,直接把备份改回来,一分钟搞定。
更进一步的做法是用 Git。在.codex目录下初始化一个 Git 仓库,每次改配置就 commit 一次。这样不仅能回滚,还能看到每次改动的 diff,知道具体改了哪一行。对于经常折腾配置的人来说,这个习惯能省下大量排查时间。
回滚的时候注意一点:config.toml和auth.json要一起回滚。只回滚一个,可能出现配置和凭证不匹配的情况,反而制造新的 401。这两个文件是绑定的,要么一起改,要么一起回。
5.4 给新手的配置检查清单
最后给刚上手的朋友一个检查清单,配完 Codex 后按这个清单过一遍,能避开大部分坑:
config.toml和auth.json都在正确的目录下(~/.codex/或C:\Users\用户名\.codex\)config.toml里base_url和auth.json里 Key 所属平台一致config.toml里env_key的值和auth.json里的键名完全一致(大小写敏感)- Key 值没有多余的空格、换行符
config.toml是合法的 TOML 格式,没有语法错误model字段填的模型名在 provider 支持列表里- 没有意外的环境变量覆盖配置文件
- 项目目录下没有旧的配置文件在"压着"全局配置
这八条过完,401 和配置不生效的问题基本就绝迹了。配置这东西,前期多花十分钟检查,后期能省十小时排查。我在实际使用中的体会是,Codex 的配置体系不算复杂,但细节多,而 401 这类报错恰恰都是细节问题。把细节抠到位,工具才能真正为你所用。