
1. 一次订阅登录失效的完整复盘事情的起因很典型我在本地用 CCswitch 管理多个模型的接入配置顺手把 Codex 的config.toml改成了指向第三方中转端点结果重启 Codex 之后原本正常的订阅登录直接失效了——界面反复提示重新登录登录完又跳回未登录状态终端里还时不时冒出codex auth token is unavailable这类报错。更麻烦的是ChatGPT 侧边栏里那条对话串直接提示cant load config.toml, so this thread cant resume等于把历史会话也一起锁死了。这个问题的本质其实不是登录坏了而是配置文件被改坏之后Codex 的鉴权链路和模型路由链路同时错位。Codex 这套工具的运行逻辑是auth.json负责存凭证订阅登录产生的 tokenconfig.toml负责声明模型、provider、端点等运行参数。两者是解耦的但一旦config.toml里的 provider 指向了一个和订阅体系不匹配的端点Codex 就会认为当前凭证对这个 provider 无效于是触发重新登录而重新登录拿到的凭证又是绑定官方订阅体系的写回去之后依然对不上那个被改过的 provider就形成了死循环。我前后折腾了大概两个小时中间试过重装、清缓存、换账号最后才定位到根因。这篇就把整个排查链路、修复步骤、以及后续怎么避免再踩这个坑完整写一遍。适合两类人看一是已经用 CCswitch 改过 Codex 配置、现在登录不上的二是准备用 CCswitch 接多个模型、想提前知道哪些字段不能乱动的。哪怕你只是刚装完 Codex、还没碰过配置文件看完也能明白这几个文件各自管什么出问题时知道先看哪里。2. auth.json 与 config.toml 的职责边界2.1 两个文件到底谁管什么很多人一出问题就想着把配置全删了重来但在动手之前得先搞清楚这两个文件的分工否则删错了地方问题只会更乱。auth.json是凭证仓库。你通过订阅方式登录 Codex 之后拿到的 access token、refresh token、账号标识、过期时间这些全部落在这个文件里。它的特点是内容由登录流程自动写入正常情况下你不需要手动编辑。它的位置通常在用户目录下的 Codex 配置目录里Windows 和 macOS/Linux 的路径不一样但都在各自的用户配置根目录下。config.toml是运行参数声明。它管的是用哪个模型、走哪个 provider、端点地址是什么、超时多少、是否开启某些实验特性。它不存凭证只声明我要用什么东西、怎么用。关键点在于provider 决定了 Codex 拿哪份凭证去请求。当你把 provider 改成第三方中转时Codex 会尝试用auth.json里的凭证去请求那个中转端点。如果这个中转端点不接受官方订阅体系的凭证绝大多数情况下都不接受鉴权就失败Codex 就判定你没登录于是弹登录框。你登录完凭证更新了但 provider 还是那个不匹配的中转于是再次失败。提示判断问题出在哪个文件有个简单办法——如果报错里出现auth token is unavailable、反复要求登录优先怀疑auth.json和 provider 的匹配关系如果报错里出现model is not supported、cant load config.toml优先怀疑config.toml的语法或字段值。2.2 为什么 CCswitch 一改就容易出事CCswitch 的设计初衷是帮你快速切换不同模型的接入配置它会直接改写config.toml里的 provider、model、base_url 等字段。问题在于它默认的切换逻辑是整体替换而不是增量合并。也就是说你从官方订阅切到某个第三方模型时它可能把 provider 段整个换掉顺带把一些和订阅体系绑定的字段也覆盖了。我实测下来最容易出问题的三个字段是字段作用被改坏后的典型症状model_provider指定当前使用的 provider 名称登录后仍提示凭证无效model指定模型标识报model is not supportedbase_urlprovider 的请求端点请求发不出去或返回鉴权错误这三个字段只要有一个和auth.json里的凭证体系对不上就会触发登录失效。而 CCswitch 在切换时往往只改了config.toml没有同步处理auth.json于是就出现了配置改了、凭证没跟上的错位。2.3 一个容易被忽略的细节会话串的绑定热词里提到的chatgpt cant load config.toml, so this thread cant resume其实揭示了一个更深的问题部分会话串在创建时会把当时的 config 快照一起记下来。当你后来改了config.toml这条会话在恢复时发现当前配置和创建时不一致或者配置本身已经语法错误就会拒绝恢复。这意味着即使你后来把配置改回来了某些历史会话可能依然打不开。这不是 bug而是设计上的一种保护——避免用错误的配置去续接一段上下文。遇到这种情况新建会话通常就能正常历史会话能不能恢复取决于它当时记录的快照是否还能被解析。3. 从报错到根因的逐步定位过程3.1 第一步确认报错到底来自哪一层排查最忌讳一上来就乱改。我的做法是先分层确认是网络层、鉴权层还是配置解析层。先看终端输出。如果 Codex 启动时直接报cant load config.toml那基本可以确定是配置解析层的问题也就是 TOML 语法错了或者某个字段的值类型不对比如该是字符串的写成了数字。这种情况 Codex 连启动都完成不了根本走不到鉴权那一步。如果启动正常但一发起请求就报auth token is unavailable那是鉴权层的问题说明配置能解析但凭证和 provider 对不上。如果报的是local proxy failed while handling codex endpoint /responses那多半是网络层或中转层的问题说明请求发出去了但对端没正常响应。我这次遇到的是前两种混合先报配置加载失败改完语法后又变成鉴权失败。所以排查必须一层一层来不能跳。3.2 第二步把 config.toml 拉出来逐字段核对确认是配置层之后我做的第一件事是把config.toml完整打印出来逐字段核对。重点看这几项model_provider的值是否和某个已定义的 provider 段名称一致对应 provider 段里的base_url是否是一个真实可达的地址model的值是否是当前 provider 支持的模型标识有没有重复定义的段或者被注释掉一半的残留内容我当时的config.toml里CCswitch 写入了一个新的 provider 段但旧的 provider 段没删干净导致同名段出现了两次。TOML 解析器遇到重复键会直接报错这就是cant load config.toml的直接来源。注意TOML 对重复键是零容忍的。同一个表里出现两个同名键或者两个同名的表头都会导致整个文件解析失败。CCswitch 在多次切换后很容易留下这种残留。3.3 第三步验证 auth.json 是否还完整配置语法修好之后登录依然失败这时候就要看auth.json了。我没有直接打开看内容里面有敏感凭证而是通过 Codex 的登录状态命令来间接判断如果它显示未登录或者凭证已过期说明auth.json要么被清空了要么里面的 token 已经失效。这里有个经验CCswitch 某些版本在切换 provider 时会顺带触发一次凭证刷新或清理。如果你的auth.json在切换后变成了空对象或者只剩一个空壳那登录失效就是必然的。判断方法是看文件大小——正常的auth.json至少有几百字节如果只有几十字节甚至 0 字节基本就是被清空了。3.4 第四步确认 provider 与凭证体系的匹配关系这是最关键的一步也是最容易被跳过的一步。很多人修好了语法、确认了凭证存在但登录还是失败就是因为没意识到官方订阅体系的凭证只能用于官方 provider。Codex 的订阅登录拿到的凭证是绑定官方服务体系的。当你把 provider 指向第三方中转时这个凭证对中转端点无效。反过来如果你用第三方中转的 key那也不该走订阅登录流程。所以正确的状态应该是二选一用官方订阅provider 保持官方默认auth.json里是订阅凭证config.toml里不要出现第三方 base_url。用第三方模型provider 指向第三方凭证用第三方提供的 key通常写在环境变量或 provider 段的配置里不要走订阅登录。我这次的问题就是混用了provider 指向第三方但凭证还是订阅体系的两边对不上。4. 让订阅登录恢复正常的实操步骤4.1 先备份再动手不管后面怎么改第一步永远是备份。把当前的config.toml和auth.json各复制一份加上时间戳后缀。这样即使改错了也能一键回滚。# 以类 Unix 系统为例Windows 下把路径换成对应的用户配置目录 cp ~/.codex/config.toml ~/.codex/config.toml.bak.$(date %Y%m%d%H%M) cp ~/.codex/auth.json ~/.codex/auth.json.bak.$(date %Y%m%d%H%M)备份的意义不只是防错更重要的是当你改了半天没改好可以直接回到至少能启动的状态而不是在一个越来越乱的文件上继续折腾。4.2 把 config.toml 恢复成订阅可用的最小配置订阅登录要能正常工作config.toml需要回到一个干净的状态。所谓干净就是只保留官方 provider 相关的声明不掺杂任何第三方端点。具体做法是把 CCswitch 写入的第三方 provider 段整段删掉把model_provider改回官方默认值把model改回官方支持的模型标识。如果你不确定官方默认值是什么最稳妥的办法是把config.toml整个删掉让 Codex 在下次启动时重新生成一份默认配置。# 恢复后的 config.toml 大致长这样字段名以你本地实际版本为准 model_provider openai model gpt-5 [model_providers.openai] name openai base_url https://api.openai.com/v1这里要强调一点不要凭记忆手写字段名。不同版本的 Codex 字段名可能有差异手写很容易写错。让工具自己生成默认配置是最不容易出错的方式。4.3 清理 auth.json 并重新走一次登录配置恢复之后auth.json里可能还残留着之前错位状态下写入的无效凭证。这时候需要把它清掉让 Codex 重新走一次完整的登录流程。做法很简单删掉auth.json或者把它重命名备份然后重新启动 Codex触发登录。登录成功后Codex 会写入一份全新的、和当前 provider 匹配的凭证。# 备份并移除旧的 auth.json mv ~/.codex/auth.json ~/.codex/auth.json.old # 然后重新启动 Codex按提示完成登录登录完成后先别急着改任何配置直接发一条最简单的请求验证一下。如果这条请求能正常返回说明订阅登录已经恢复。4.4 验证登录状态是否真正恢复验证不能只看界面显示已登录因为界面状态有时候是缓存的。真正的验证是发一次实际请求并拿到正常响应。我通常会做三个层次的验证启动 Codex确认没有cant load config.toml之类的解析报错。发一条短请求确认能正常返回内容没有auth token is unavailable。打开一条历史会话确认能正常恢复如果之前被锁的话。三步都过了才算真正修好。只过前两步、第三步失败说明会话快照的问题还在需要单独处理。5. 用 CCswitch 接多模型时怎么不踩这个坑5.1 切换前先确认凭证体系CCswitch 最大的价值是快速切换但切换的前提是凭证体系要跟着切。我的经验是每次用 CCswitch 切到一个新 provider 之前先问自己一句——这个 provider 用的是哪套凭证如果是官方订阅体系那就不要动 provider 相关字段只切模型如果是第三方那就准备好第三方的 key并且明确知道这个 key 该写在哪里。最忌讳的就是provider 切了、凭证没切这正是登录失效的根源。5.2 给每个 provider 单独建配置片段与其让 CCswitch 反复覆盖同一个config.toml不如给每个 provider 维护一份独立的配置片段切换时整体替换而不是增量修改。这样做的好处是每次切换后的状态都是确定的、可预期的不会出现改了一半的中间态。具体做法是在配置目录下建几个文件比如config.openai.toml、config.thirdparty.toml切换时直接复制覆盖config.toml。这样即使某个片段有问题也不会污染其他片段。5.3 切换后必做的三项检查每次切换完我都会做三项检查形成习惯之后基本不会再出登录问题检查config.toml有没有重复段或残留内容用 TOML 校验工具过一遍。检查auth.json是否还存在、大小是否正常。发一条测试请求确认鉴权链路通。这三项加起来不到一分钟但能挡掉绝大多数切完就登录不上的情况。5.4 遇到会话串无法恢复怎么办如果历史会话提示cant load config.toml, so this thread cant resume先别慌。这个提示的意思是当前配置无法解析所以这段会话没法续接而不是这段会话的数据丢了。处理顺序是先把config.toml修好确认能正常解析然后重新打开那条会话。如果还是打不开说明这条会话创建时记录的快照和当前配置差异太大这种情况下新建会话是最快的解决办法。历史内容如果重要可以在修复配置后尝试导出或复制关键内容到新会话里。6. 几个高频报错的对应处理6.1 model is not supported 的排查思路这个报错的意思是你声明的模型当前 provider 不支持。常见原因有两个一是模型标识写错了比如把版本号写错二是 provider 和模型不匹配比如用官方 provider 去请求一个只有第三方才有的模型。处理办法是先确认 provider 支持哪些模型再把model字段改成受支持的标识。不要凭感觉写模型名尤其是带版本号的差一个字符就会报这个错。6.2 auth token is unavailable 的三种可能这个报错我遇到过三种情况auth.json被清空或损坏——重新登录即可。provider 和凭证体系不匹配——把 provider 改回和凭证匹配的值。凭证过期且刷新失败——删掉auth.json重新走登录。排查顺序建议从 1 到 3因为前两种处理成本最低。6.3 local proxy failed 的定位方法这个报错通常和网络层有关说明请求发出去了但对端没正常响应。定位方法是先确认base_url是否可达用简单的网络请求测一下再确认端点路径是否正确有些中转的路径和官方不一样最后确认请求头里的鉴权信息是否符合对端要求。如果base_url本身就不通那问题不在 Codex而在网络或对端服务。这种情况下改 Codex 配置是没用的。6.4 配置改回后仍无法登录的兜底方案如果所有配置都改回了、凭证也重新登录了但依然登录不上那就用兜底方案把整个 Codex 配置目录备份后清空让它从零开始。# 备份整个配置目录 mv ~/.codex ~/.codex.bak.$(date %Y%m%d%H%M) # 重新启动 Codex它会生成全新的默认配置这个方案相当于恢复出厂设置能解决绝大多数因为配置残留导致的疑难问题。代价是之前的自定义配置和部分本地状态会丢失所以一定要先备份。7. 我在实际使用中总结的几条经验折腾完这一轮我最大的体会是Codex 的配置问题九成出在改的时候没想清楚改的是哪一层。auth.json和config.toml是两个独立的层改配置的时候如果没意识到凭证层也要跟着动就一定会出问题。第二条经验是CCswitch 这类工具方便但不能完全托管。它帮你改配置但不会帮你判断这个改动会不会破坏凭证匹配。所以每次切换后自己花一分钟做那三项检查比事后花两小时排查划算得多。第三条是关于备份的。我以前觉得备份麻烦直到有一次改坏了配置、又没备份只能重装。从那以后我养成了改配置前先复制一份的习惯。这个习惯救过我很多次尤其是在试新 provider 的时候。最后分享一个小技巧如果你经常在多个 provider 之间切换可以写一个简单的切换脚本把备份当前配置、复制目标配置、校验 TOML、发测试请求这几步串起来。这样每次切换都是一键完成既快又不容易出错。脚本本身不复杂核心就是把上面那几项检查自动化省去手动核对的麻烦。