bug(runtime): OpenAI OAuth (Codex) connection fails every turn — resolved input limit (922k) exceeds the pinned context window (272k)
- Dominant language
- TypeScript
- Stars
- 5.4k
- Forks
- 502
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 716
Description
## What happened
On my machine the **OpenAI OAuth (ChatGPT / Codex)** connection (`providerType: openai-codex`) cannot start **any** turn. Every send fails before a request is ever built, including a brand-new session whose only message is `你好`:
```
Model input limit exceeds the context window. Update the model limits.
```
This is thrown by `resolveSelectedModelContextWindow()` in `packages/runtime/src/context-budget-policy.ts` when `modelLimitsConflict()` sees a resolved `inputLimit` larger than the resolved `contextWindow`. On this connection the two facts resolve to:
| Fact | Value | Source |
| --- | --- | --- |
| `contextWindow` | 272,000 | connection inventory — `connection-catalog.json` (schema 2), `models[].contextWindow`, `modelSource: "fetched"` |
| `inputLimit` | 922,000 | models.dev metadata — `openai/gpt-5.6-terra` (the same value appears for luna / sol / gpt-5.5 / gpt-5.4) |
272,000 < 922,000, so the runtime refuses to build the backend. I expected the turn to run, or at worst to be rejected with the provider's own answer — the two numbers describe the same model, so one of them being wrong should not make the model unusable.
This is **not** a context-length problem:
* Fresh session, one message (`你好`): `invocation_opened` → user text → `error` within **5 ms**. No provider request is constructed.
* The throw happens at backend activation (`RuntimeKernel.ensureActive` → `buildHostAiSdkBackend`), not while streaming.
* Other connections on the same build work normally in the same minutes — `xai-oauth/grok-4.6`, `deepseek/deepseek-flash`, `opencode-go/deepseek-v4.1-flash` — including runs started *after* the failing ones.
The desktop surfaces it as a generic toast ("任务运行失败,请稍后重试" / `missing_terminal_event`), which invites retries that cannot succeed.
## How to reproduce
1. Install the official nightly on Windows and sign in to **Settings → Models → OpenAI OAuth (ChatGPT / Codex)**; the connection test reports `verified`.
2. Select `gpt-5.6-terra` (or `gpt-5.5`) for a session.
3. Send any message — a new session with a single `你好` is enough.
4. The turn ends immediately with the error above; **Regenerate** reproduces it identically (3 attempts on my machine).
Observed on this machine, one connection, one day:
| Time (UTC) | Model | Result |
| --- | --- | --- |
| 06:46:51 | `gpt-5.6-luna` | **success** — the turn's usage fact records `contextRemaining: 918047` (= 922,000 − 3,953 input tokens) |
| 06:46:55 | — | connection inventory written: `modelSource: "fetched"`, `modelsFetchedAt`, and `contextWindow: 272000` for terra / luna / gpt-5.5 |
| 07:14:41 – 07:19:28 | `gpt-5.5`, then `gpt-5.6-terra` | 5 consecutive failures on the same stored prompt (3 of them explicit regenerates) |
| 07:23:30 | `gpt-5.6-terra` | new session, single message, same failure |
The 06:46:51 success shows the 922k input limit alone is not a conflict; the failures begin at the point where the connection inventory pins the window to 272k. Whether the failure is deterministic on a fresh install of this nightly, or depends on the connection having run model discovery once, I cannot tell from a single machine.
## Environment
- Maka version: `0.2.0-dev.31.20260913` (packaged installer, nightly channel)
- OS and version: Windows 11 (10.0.26200, x64)
- Surface: Desktop (renderer + local Runtime Host)
- Electron 43.4.1, Node 24.18.1 (as reported by the app)
- Connection: `openai-codex` — "OpenAI OAuth (ChatGPT / Codex)", OAuth sign-in
- Affected models: `gpt-5.6-terra`, `gpt-5.5` (by the numbers below, `gpt-5.6-luna`, `gpt-5.6-sol` and `gpt-5.4` are in the same state)
## Logs, screenshots, or additional context
### Where the conflict comes from (current `main`)
`packages/core/src/model-metadata.ts` — the OAuth path pins its own windows but spreads the models.dev base, which carries the input limit:
```ts
function openAiOAuthBase(active, modelId) {
return active.openai?.[modelId] ?? GENERATED_MODELS_DEV_METADATA.openai[modelId] ?? {};
}
function openAiOAuthModelMetadata(active) {
return {
'gpt-5.6-sol': { ...openAiOAuthBase(active, 'gpt-5.6-sol'), contextWindow: 372_000, ... },
'gpt-5.5': { ...openAiOAuthBase(active, 'gpt-5.5'), contextWindow: 272_000 },
'gpt-5.4': { ...openAiOAuthBase(active, 'gpt-5.4'), contextWindow: 272_000 },
'gpt-5.4-mini': { ...openAiOAuthBase(active, 'gpt-5.4-mini'), contextWindow: 272_000 },
...
};
}
```
models.dev declares `contextWindow: 1_050_000` and `inputLimit: 922_000` for `gpt-5.6-terra` / luna / sol / gpt-5.5 / gpt-5.4, so after the pin the pair becomes 272,000 / 922,000 (372,000 / 922,000 for sol).
`packages/core/src/model-thinking.ts` resolves the two facts **independently** (`override ?? model ?? metadata`), so a window taken from the connection inventory can be paired with an input limit taken from metadata:
```ts
const contextWindow = override?.contextWindow ?? model.contextWindow ?? metadata.contextWindow;
const inputLimit = override?.inputLimit ?? model.inputLimit ?? metadata.inputLimit;
```
Both files and the throwing guard are unchanged on `main` as of the 2026-09-14 07:10 UTC commits, so this is reproducible today rather than a stale nightly.
PR #5225 (merged 2026-09-12, `connection-catalog.json` schema 2, compatibility epoch 149) is where a resolved conflict became a hard failure; its own CI note describes the same shape on the Codex history-compaction fixture ("reduced total capacity to 32K but inherited a larger metadata input limit under the new per-field resolver"). My build is the nightly after that merge.
For reference, `gpt-5.4-mini` resolves to 272,000 / 272,000 (metadata declares 400,000 / 272,000) and should not conflict — I have not exercised it on the subscription.
### Question for maintainers
Where does the 272,000 for `gpt-5.6-terra` / `gpt-5.6-luna` come from? The pin table above lists sol / gpt-5.5 / gpt-5.4 / gpt-5.4-mini but **not** terra or luna, yet the persisted connection inventory carries 272,000 for terra and luna too. If the Codex endpoint's model list reports its own window, then the pinned values and the discovered ones need a single owner; if that number is derived elsewhere, that path is what pins a window below the inherited input limit. I could not distinguish the two from the packaged build alone.
### Two smaller points from the same failure
1. For a deterministic configuration conflict the toast says "please retry later". The failure is stable until the model or its limits change, so the message sends users into a retry loop.
2. The rule is already enforced at the settings boundary — the form rejects `modelLimitsConflict` with "输入上限不能超过上下文窗口" — but a conflict produced by *resolved* limits is only discovered at send time, on the first turn.
### Workaround
Switching the session to another connection works. Declaring both facts for the model in connection settings so that `input limit ≤ context window` (e.g. window 272,000 / input limit 262,144) should also clear it, since a user declaration is the first fallback in `resolveModelLimits()` — I have not verified that path yet, and will follow up here if I test it.
中文
## 问题描述
本机使用 **OpenAI OAuth(ChatGPT / Codex)** 连接(`providerType: openai-codex`)时,**任何**一轮任务都无法开始,包括全新会话里只发一句「你好」:
```
Model input limit exceeds the context window. Update the model limits.
```
抛出点是 `packages/runtime/src/context-budget-policy.ts` 的 `resolveSelectedModelContextWindow()`:当 `modelLimitsConflict()` 发现解析出来的 `inputLimit` 大于 `contextWindow` 时就抛错。该连接上这两个事实分别是 **272,000**(连接目录 `connection-catalog.json`,schema 2,`models[].contextWindow`,`modelSource: "fetched"`)与 **922,000**(models.dev 的 `openai/gpt-5.6-terra`,luna / sol / gpt-5.5 / gpt-5.4 同值),因此运行时直接拒绝建立后端。预期是这一轮能跑起来,或者至少由供应商给出真实拒绝;两个数字描述的是同一个模型,其中一个不对不应该让模型完全不可用。
不是上下文长度问题:
- 全新会话、单条消息:`invocation_opened` → 用户文本 → `error`,全程 **5 毫秒**,请求根本没构造。
- 抛出发生在后端激活阶段(`ensureActive` → `buildHostAiSdkBackend`),不在流式回复过程中。
- 同一时间段内其他连接正常:`xai-oauth/grok-4.6`、`deepseek/deepseek-flash`、`opencode-go/deepseek-v4.1-flash`,包括在失败之后才发起的运行。
- 重试是确定性的:三次「重新生成」得到完全相同的错误。
## 复现步骤
1. 在 Windows 上安装官方 nightly,在「设置 → 模型 → OpenAI OAuth(ChatGPT / Codex)」登录,连接测试显示 `verified`。
2. 为会话选择 `gpt-5.6-terra`(或 `gpt-5.5`)。
3. 发送任意消息——新会话只发一句「你好」即可。
4. 该轮立刻以上述错误结束;点「重新生成」结果相同(本机 3 次)。
## 时间线(同一连接)
| 时间 (UTC) | 模型 | 结果 |
| --- | --- | --- |
| 06:46:51 | `gpt-5.6-luna` | **成功**,用量事实记录 `contextRemaining: 918047`(= 922,000 − 3,953) |
| 06:46:55 | — | 写入连接目录:`modelSource: "fetched"`、`modelsFetchedAt`,terra / luna / gpt-5.5 各自带上 `contextWindow: 272000` |
| 07:14:41 – 07:19:28 | `gpt-5.5`、随后 `gpt-5.6-terra` | 连续 5 次失败(其中 3 次是显式「重新生成」) |
| 07:23:30 | `gpt-5.6-terra` | 新会话、单条消息,同样失败 |
06:46:51 那次成功说明 922k 的输入上限本身并不冲突;失败从连接目录把窗口钉到 272k 那一刻开始。
## 环境
Maka `0.2.0-dev.31.20260913`(打包安装版,nightly),Electron 43.4.1,Node 24.18.1,Windows 11(10.0.26200,x64),Desktop 界面 + 本地 Runtime Host。
## 冲突来源与疑问
`packages/core/src/model-metadata.ts` 的 `openAiOAuthModelMetadata()` 为 OAuth 路径钉住窗口,但展开的 models.dev 基础里带着输入上限;`packages/core/src/model-thinking.ts` 的 `resolveModelLimits()` 把两个事实各自独立解析(`override ?? model ?? metadata`);`packages/runtime/src/context-budget-policy.ts` 再拒绝这一对。截至 2026-09-14 07:10 UTC 的提交,`main` 上这几个文件和这条规则都没有变化。
想请教:`gpt-5.6-terra` / `gpt-5.6-luna` 的 272,000 从哪来?上面的钉表只列了 sol / gpt-5.5 / gpt-5.4 / gpt-5.4-mini,但持久化的连接目录里 terra 与 luna 也是 272,000。若是 Codex 端点自己的模型列表上报的窗口,那么「钉住的窗口」和「发现到的窗口」需要一个归属方;若是别处推导出来的,那条路径就是把窗口压到继承输入上限之下的地方。仅从打包产物无法区分。
## 另外两点
1. 对确定性配置冲突,toast 却提示「请稍后重试」,会把用户带进无意义的重试循环。
2. 这条规则在设置表单里已经有校验(`输入上限不能超过上下文窗口`),但由**解析结果**产生的冲突只在发送时、在第一次任务上才暴露。
## 临时绕过
把会话切到其他连接可用;在连接设置里为该模型同时声明上下文窗口与输入上限、使输入上限 ≤ 上下文窗口(例如窗口 272,000 / 输入上限 262,144)预期也能解除,因为用户声明是 `resolveModelLimits()` 的第一优先级——这条尚未实测,测过会在这里补充。
AI assistance: the observations were collected and cross-checked with DeepSeek Harness (local runtime event database, the packaged `app.asar`, and current `main` sources). Everything above is from recorded run data, except the explicitly-labelled workaround, which is untested.
Contributor guide
Assessment
This issue has not been assessed yet.