Codex CLI Proxy Configuration Troubleshooting: A Complete Account of a 401 Error and the Pitfalls I Encountered
When connecting to third-party relay servers with the new Codex CLI (tested with v0.145.0), the most common error is a series of 401 responses. This article outlines the correct way to write the `config.toml` file, three common pitfalls, and verification methods—you can use it as a troubleshooting checklist and copy the instructions directly.
- 7 min read
- 2026.08.04
The key to connecting Codex CLI to third-party relay servers is: the `base_url` must be written inside the [model_providers.xxx] block and referenced by the top-level `model_provider`; if written directly at the top level, it will be completely ignored by the new version. Use the top-level `experimental_bearer_token` for authentication; do not rely on environment variables.
Troubleshooting Codex CLI Integration with a Relay Server
When setting up the new version of Codex CLI to connect to a third-party relay server, users often get stuck at one point: even though they’ve entered the relay server’s address and key, requests still end up at api.openai.com, followed by a series of 401 Unauthorized errors.
This article documents my complete process of connecting Codex CLI (including the Codex built into the ChatGPT desktop app; tested with v0.145.0) to a relay server: the correct configuration syntax, three common pitfalls, and how to verify that the connection is working properly. You can use this as a troubleshooting checklist and follow the steps exactly.
Conclusion First: The Correct config.toml The configuration file is located at ~/.codex/config.toml (C:\Users\你\.codex\config.toml on Windows). Here is the minimal configuration that works:
model = "gpt-5.6-sol" # 换成中转站支持的模型名
model_reasoning_effort = "high"
model_provider = "qnvip" # 指向下面的 provider 块
experimental_bearer_token = 'sk-xxxxxxxx' # 中转站的 key,鉴权用
[model_providers.qnvip]
name = "qnvip"
base_url = "http://中转站域名/v1"
wire_api = "responses" # 中转站不支持 responses 就改成 "chat"
Structurally, there are only three things that must align:
- The value of the top-level
model_provideris equal to thexxxvalue inside[model_providers.xxx]. base_urlis defined inside theproviderblock, not at the top level.- Authentication uses the top-level
experimental_bearer_tokenand does not rely on environment variables.
What the Error Looks Like
When a connection fails, the most common error message looks like this:
请求根本没走中转站
401 Unauthorized: Incorrect API key provided: sk-xxxx...
- https://api.openai.com/v1/responses
- 报错里的 url 是 api.openai.com,而不是你的中转站域名
- 说明 Codex 用的是内置 openai provider,没读到你的配置
- 中转站的 key 拿到官方接口当然无效 → 401
Three Common Pitfalls
Pitfall 1: base_url Written directly at the top level → Completely ignored (Main Cause)
This is where the vast majority of people get stuck. The new version of Codex does not recognize the top-level base_url. If there is no [model_providers.xxx] block with a reference to model_provider, it falls back to the built-in OpenAI provider, which is hardcoded to api.openai.com.
| Approach | Result |
|---|---|
❌ base_url Written directly at the top level | Silently ignored with no error messages; request routed to api.openai.com, resulting in a 401 |
✅ base_url Written inside the [model_providers.xxx] block | Works in conjunction with model_provider at the top level; request correctly routed to the relay station |
Incorrect Syntax (Directly written at the top level; invalid):
base_url = "http://中转站域名/v1" # ❌ 被忽略
wire_api = "responses"
Pitfall 2: An Extra Quotation Mark at the End of the Key
It’s very easy to make a typo when copying and pasting a key. For example, with 'sk-...4eb5"' — the extra " at the end will be treated as part of the key, corrupting the entire key. As a result, even if the provider is paired correctly, the relay will report invalid_api_key.
Pitfall 3: Custom Provider Not Reading auth.json In the Codex built into the ChatGPT desktop app, there’s a auth.json, and the OPENAI_API_KEY within it is exclusively for the built-in OpenAI provider. If a custom provider specifies env_key = "OPENAI_API_KEY", it reads the actual system environment variables instead of auth.json, resulting in the following error:
Missing environment variable: OPENAI_API_KEY
Two Solutions—I Recommend the First One:
- ✅ Use top-level
experimental_bearer_token: No reliance on environment variables; works reliably whether launched from the command line or via the desktop app. - ⚠️ Alternatively, use
export OPENAI_API_KEY=sk-xxxand then specifyenv_key = "OPENAI_API_KEY"in the provider. Note that when launching the desktop app, it may not inherit the exports from~/.zshrc, which can cause inconsistent behavior.
Configuration Process Overview
Translating the three pitfalls above into step-by-step instructions results in the following path:
Completed: 写 provider 块
在 [model_providers.xxx] 里填 name、base_url、wire_api
Completed: 顶层指向 provider
设置 model_provider = "xxx",与块名一致
Completed: 配置鉴权
用 experimental_bearer_token 填中转站 key,检查引号成对
Current: 在受信任目录验证
用 codex exec 跑一条测试请求,确认 provider 生效
Verification Methods
It must be run in a trusted directory; otherwise, it will return Not inside a trusted directory:
cd /受信任的项目目录
echo "只回复两个字:成功" | codex exec --skip-git-repo-check
Check the startup logs to see if “provider:” is your relay station name and whether content is being returned normally. If you see the word “Success,” it means the entire connection is working properly.
Quick Reference Table for Errors
I’ve compiled a table of common errors and their corresponding causes—if you run into a problem, just check the table to see what it is:
| Error | Cause | Resolution |
|---|---|---|
401 and the URL is api.openai.com | base_url Did not enter the provider block / provider not active | Check if model_provider and [model_providers.xxx] match |
401 invalid_api_key (URL is a relay server) | Incorrect key / key contains extra characters | Recopy the key and ensure all quotation marks are properly paired |
Missing environment variable: OPENAI_API_KEY | env_key is used but environment variables are not set | Switch to experimental_bearer_token |
| 404 / Incorrect path | wire_api is set to responses, but the relay server only supports "chat" | Change to "chat"; or check if /v1 is missing or extra in base_url |
Not inside a trusted directory | Not in a trusted directory | Add --skip-git-repo-check or run it from a trusted directory |