Client or integration
Codex App
Area
Catalog / models
Summary
Namespaced routed models can work in a normal locally-created Codex App task, but after task rollback / thread settings restoration the next turn can be rejected before it reaches OpenCodex:
The 'subapi/gpt-5.6-sol' model is not supported when using Codex with a ChatGPT account.
The restored task settings contain:
model = subapi/gpt-5.6-sol
model_provider_id = openai
Re-selecting the same namespaced model in the picker does not help because it writes the same model/provider combination. Removing provider prefixes is not a viable workaround: users need both gpt-5.6-sol (native OpenAI) and subapi/gpt-5.6-sol (routed provider) to remain independently selectable.
This appears to be a regression/variant of #17, now triggered by rollback/settings restoration on a local Codex App task rather than mobile thread creation.
Reproduction
- Run OpenCodex on loopback and sync its generated model catalog into Codex App.
- Use a ChatGPT account in Codex.
- Select a namespaced routed model such as
subapi/gpt-5.6-sol.
- Start and continue a local task successfully; requests reach OpenCodex and route to
subapi.
- Roll back one turn (or otherwise cause Codex to restore/reapply the task's thread settings).
- Send the next message.
- Codex returns HTTP 400 with the unsupported-model message before OpenCodex receives the turn.
- Re-select
subapi/gpt-5.6-sol and retry; the same error occurs.
Observed rollout evidence:
thread_settings_applied:
model: subapi/gpt-5.6-sol
model_provider_id: openai
task_started
task_complete after 5.6 s:
status: 400
invalid_request_error:
The 'subapi/gpt-5.6-sol' model is not supported when using Codex with a ChatGPT account.
There is no matching OpenCodex usage/request row for the rejected turn, while earlier turns in the same task do have successful provider=subapi rows. This places the failure before the local proxy.
Why the current loopback integration is vulnerable
src/codex/inject.ts documents Design B: loopback installs override the built-in provider with root openai_base_url and deliberately leave thread history as model_provider = "openai".
That works for ordinary forwarding, but it also means a namespaced third-party catalog model is restored as an openai/ChatGPT-account model. Codex's rollback/resume path can then apply official-account model validation before using the overridden base URL.
Proposed change
Keep Design B as the default, but add a supported dedicated-provider compatibility mode for installations that expose namespaced routed models, for example:
{
"codexIntegrationMode": "dedicated-provider"
}
In that mode OpenCodex would use its existing provider-table/history machinery:
model_provider = "opencodex"
[model_providers.opencodex]
name = "OpenCodex Proxy"
base_url = "http://127.0.0.1:10100/v1"
wire_api = "responses"
requires_openai_auth = true
Requirements:
- Preserve namespaced catalog IDs exactly; do not strip
subapi/ or rewrite upstream response model values.
- Preserve native and routed choices independently (
gpt-5.6-sol and subapi/gpt-5.6-sol). OpenCodex remains the router for both.
- Ensure new, resumed, rolled-back, and restored tasks consistently retain
model_provider_id=opencodex in this mode.
- Keep injection journal/restore behavior and history migration reversible.
- Add an integration test covering
thread_settings_applied after rollback with a namespaced model and ChatGPT authentication.
- If Codex itself still rejects the dedicated provider path, detect this during
ocx sync and report a clear compatibility warning rather than exposing a selectable model that fails before proxy admission.
An automatic mode is also possible, but an explicit compatibility switch is safer initially because Design B intentionally avoids history retagging.
Expected behavior
A namespaced routed model that is selectable and works on a task's first turn should continue to work after rollback/resume. The request should reach OpenCodex and be routed by its namespace, without being validated as an official OpenAI model solely because the user authenticates Codex with a ChatGPT account.
Version
OpenCodex 2.10.2; Codex App/CLI 0.147.0-alpha.1.2
Operating system
macOS 15.6.1 (24G90)
Provider and model
Custom OpenAI Responses-compatible provider (subapi) / subapi/gpt-5.6-sol
Redacted configuration
{
"port": 10100,
"websockets": false,
"streamMode": "eager-relay",
"defaultProvider": "subapi",
"providers": {
"subapi": {
"adapter": "openai-responses",
"baseUrl": "https://REDACTED/v1"
}
}
}
Checks
Client or integration
Codex App
Area
Catalog / models
Summary
Namespaced routed models can work in a normal locally-created Codex App task, but after task rollback / thread settings restoration the next turn can be rejected before it reaches OpenCodex:
The restored task settings contain:
Re-selecting the same namespaced model in the picker does not help because it writes the same model/provider combination. Removing provider prefixes is not a viable workaround: users need both
gpt-5.6-sol(native OpenAI) andsubapi/gpt-5.6-sol(routed provider) to remain independently selectable.This appears to be a regression/variant of #17, now triggered by rollback/settings restoration on a local Codex App task rather than mobile thread creation.
Reproduction
subapi/gpt-5.6-sol.subapi.subapi/gpt-5.6-soland retry; the same error occurs.Observed rollout evidence:
There is no matching OpenCodex usage/request row for the rejected turn, while earlier turns in the same task do have successful
provider=subapirows. This places the failure before the local proxy.Why the current loopback integration is vulnerable
src/codex/inject.tsdocuments Design B: loopback installs override the built-in provider with rootopenai_base_urland deliberately leave thread history asmodel_provider = "openai".That works for ordinary forwarding, but it also means a namespaced third-party catalog model is restored as an
openai/ChatGPT-account model. Codex's rollback/resume path can then apply official-account model validation before using the overridden base URL.Proposed change
Keep Design B as the default, but add a supported dedicated-provider compatibility mode for installations that expose namespaced routed models, for example:
{ "codexIntegrationMode": "dedicated-provider" }In that mode OpenCodex would use its existing provider-table/history machinery:
Requirements:
subapi/or rewrite upstream response model values.gpt-5.6-solandsubapi/gpt-5.6-sol). OpenCodex remains the router for both.model_provider_id=opencodexin this mode.thread_settings_appliedafter rollback with a namespaced model and ChatGPT authentication.ocx syncand report a clear compatibility warning rather than exposing a selectable model that fails before proxy admission.An automatic mode is also possible, but an explicit compatibility switch is safer initially because Design B intentionally avoids history retagging.
Expected behavior
A namespaced routed model that is selectable and works on a task's first turn should continue to work after rollback/resume. The request should reach OpenCodex and be routed by its namespace, without being validated as an official OpenAI model solely because the user authenticates Codex with a ChatGPT account.
Version
OpenCodex 2.10.2; Codex App/CLI 0.147.0-alpha.1.2
Operating system
macOS 15.6.1 (24G90)
Provider and model
Custom OpenAI Responses-compatible provider (
subapi) /subapi/gpt-5.6-solRedacted configuration
{ "port": 10100, "websockets": false, "streamMode": "eager-relay", "defaultProvider": "subapi", "providers": { "subapi": { "adapter": "openai-responses", "baseUrl": "https://REDACTED/v1" } } }Checks