model_catalog_json from main fails in Codex App 0.148.0-alpha.9 after catalog schema change
What issue are you seeing?
The current codex-rs/models-manager/models.json from the repository's main branch cannot be loaded through model_catalog_json by the Codex binary bundled with Codex App 26.810.52044 (build 6662).
The embedded binary reports:
codex-cli 0.148.0-alpha.9
Loading the current catalog fails before any model request is made:
Error: failed to parse model_catalog_json path `/dev/stdin` as JSON: missing field `supports_parallel_tool_calls` at line 116 column 5
This is a model-catalog schema compatibility issue, not a context-window issue.
What steps can reproduce the bug?
On macOS:
curl -fsSL https://raw.githubusercontent.com/openai/codex/main/codex-rs/models-manager/models.json \
| /Applications/ChatGPT.app/Contents/Resources/codex \
-c 'model_catalog_json="/dev/stdin"' \
debug models
The command exits with the missing-field error above.
As a control, the catalog from the matching client tag loads successfully and returns all eight models:
curl -fsSL https://raw.githubusercontent.com/openai/codex/rust-v0.148.0-alpha.9/codex-rs/models-manager/models.json \
| /Applications/ChatGPT.app/Contents/Resources/codex \
-c 'model_catalog_json="/dev/stdin"' \
debug models
Environment:
Codex App bundle version: 26.810.52044
Codex App build: 6662
Embedded Codex binary: codex-cli 0.148.0-alpha.9
Platform: Darwin 24.6.0 arm64 arm
What is the expected behavior?
One of the following contracts should be explicit:
model_catalog_jsoncatalogs remain backward compatible with supported released clients.- Catalogs are versioned and users are directed to the catalog matching their Codex release.
- Cross-version catalogs are unsupported, but the configuration documentation and parse error clearly explain the client/catalog version mismatch.
The current configuration reference describes model_catalog_json as an optional catalog path, but does not state that a file copied from main must match the client release:
https://developers.openai.com/codex/config-reference
Additional information
The incompatibility appeared when supports_parallel_tool_calls was intentionally removed from both ModelInfo and the bundled catalog:
https://github.com/openai/codex/commit/86b1123ff6b5d089a146be4e603a324cf454223a
The failing current catalog is:
https://github.com/openai/codex/blob/main/codex-rs/models-manager/models.json
The working version-matched catalog is:
https://github.com/openai/codex/blob/rust-v0.148.0-alpha.9/codex-rs/models-manager/models.json
Re-adding the removed field unconditionally may not be the right fix because the field was intentionally retired. A documented version contract, a versioned catalog/schema, or a compatibility strategy would avoid treating the current main file as directly reusable by older released clients.
1 Comment
Small addendum that narrows the breakage class and suggests a low-cost compatibility contract.
The reason this particular retirement broke released clients is that on the shipped client, the field was declared required —
rust-v0.148.0-alpha.9has:(openai_models.rs L412 on that tag), while most other bools in
ModelInfocarry#[serde(default)]/#[serde(default = "default_true")]and would have tolerated the removal silently. Serde already ignores unknown fields here, so the other direction — an old catalog on a new client — is safe; the only breaking combination is "field removed from catalog while some supported client still declares it required".That suggests a cheaper contract than versioned catalogs (option 2 in the issue):
ModelInfoand friends) gets a serde default at introduction time — i.e., treat "required field in the catalog schema" as a lint failure. Then removals frommodels.jsonare non-breaking for all past clients that followed the rule, and additions are non-breaking for old clients automatically.models.json(it's dead weight for new clients, which ignore it) until the oldest supported client version has thedefaultannotation.That would make option 1 from the issue ("catalogs from
mainremain loadable by supported released clients") mostly enforceable mechanically — a CI check that deserializes the currentmodels.jsonwith the oldest-supported release's schema would catch this exact regression.