Skip to content

[Bug]: ChatGPT auth rejects namespaced routed models before OpenCodex proxy admission #1229

Description

@ShannwYang

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

  1. Run OpenCodex on loopback and sync its generated model catalog into Codex App.
  2. Use a ChatGPT account in Codex.
  3. Select a namespaced routed model such as subapi/gpt-5.6-sol.
  4. Start and continue a local task successfully; requests reach OpenCodex and route to subapi.
  5. Roll back one turn (or otherwise cause Codex to restore/reapply the task's thread settings).
  6. Send the next message.
  7. Codex returns HTTP 400 with the unsupported-model message before OpenCodex receives the turn.
  8. 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:

  1. Preserve namespaced catalog IDs exactly; do not strip subapi/ or rewrite upstream response model values.
  2. Preserve native and routed choices independently (gpt-5.6-sol and subapi/gpt-5.6-sol). OpenCodex remains the router for both.
  3. Ensure new, resumed, rolled-back, and restored tasks consistently retain model_provider_id=opencodex in this mode.
  4. Keep injection journal/restore behavior and history migration reversible.
  5. Add an integration test covering thread_settings_applied after rollback with a namespaced model and ChatGPT authentication.
  6. 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

  • I searched existing issues and documentation.
  • I removed secrets, tokens, account details, request credentials, and personal data.

Metadata

Metadata

Assignees

No one assigned

    Labels

    account-poolOAuth, credentials, Codex pool, quota, failover, plansbugSomething isn't workingcatalogModel catalog, slugs, visibility, routed entries

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions