Repository navigation
Routing capability evidence discards every catalog row (field-shape mismatch) #1796
Description
Client or integration
OpenCodex dashboard
Area
Catalog / models
Summary
candidateCapabilityEvidence() in src/routing/capability.ts reads the cached Codex catalog to source routing evidence, but its row filter expects field names the catalog writer never produces. Every row is discarded, so the catalog branch of the evidence chain is dead code.
cachedCatalogModels() filters on model.id and model.provider and then reads model.contextWindow / model.inputModalities. The on-disk catalog writes slug (a combined provider/id), context_window, and input_modalities. None of the four expected keys exist on any row.
This is not specific to one provider. On a live install with 17 catalog rows, zero survive the filter — native OpenAI rows, anthropic/claude-opus-5, xai/grok-4.6, all of them.
The defect is invisible for most providers because the catalog is the fourth fallback: a provider that declares modelContextWindows / modelInputModalities inline is answered by an earlier branch. It becomes visible for a model registered through ocx models add, whose capability metadata lives only in the catalog. Such a model routes as image-blind and context-unknown even though the CLI, the config, and the catalog file all show the correct values.
Reproduction
-
Register a custom model whose provider block declares no
modelContextWindowsand nomodelInputModalities:ocx models add <provider> <model> --context-window 262144 --modalities text,image -
Confirm the value reached the catalog file (
~/.codex/opencodex-catalog.json):{ "slug": "<provider>/<model>", "context_window": 262144, "input_modalities": ["text", "image"] } -
Assemble routing evidence for that candidate:
candidateCapabilityEvidence(config, "<provider>", "<model>") => { tools: true, serviceTier: "unsupported", encryptedCodexTasks: false }
contextWindow and image are both absent.
-
Count survivors directly:
TOTAL: 17 | SURVIVING capability.ts filter: 0
Version
2.21.0
Operating system
macOS 26 (arm64)
Provider and model
Reproduced with a local llama.cpp provider (openai-chat adapter) and a custom-registered model; the 17-to-0 count covers anthropic, xai, google-antigravity, kimi, alibaba-token-plan-intl and native OpenAI rows equally.
Logs or error output
KEYS: slug,display_name,description,default_reasoning_level,supported_reasoning_levels,
shell_type,visibility,supported_in_api,priority,...,input_modalities,...,context_window,
max_context_window,auto_compact_token_limit,...,opencodex_catalog_kind
provider? undefined id? undefined context_window? 262144
Screenshots and supporting files
Not applicable — reproduced through direct function calls.
Redacted configuration
{ "providers": { "<provider>": { "adapter": "openai-chat",
"baseUrl": "http://<host>:<port>/v1", "defaultModel": "<model>" } },
"customModels": [ { "provider": "<provider>", "modelId": "<model>",
"contextWindow": 262144, "inputModalities": ["text", "image"] } ] }Checks
- I searched existing issues and documentation.
- I removed secrets, tokens, account details, request credentials, and personal data.
Note on the naive fix
Reading context_window / input_modalities straight off the row is not a correct repair. ensureStrictCatalogFields() synthesizes both fields for Codex's strict parser (src/codex/catalog/parsing.ts:315 writes ["text"], :328 writes 128000), so their presence cannot distinguish a real provider assertion from a placeholder. Reading them would turn unknown into a confident image: false and a fabricated 128000, violating the module's own "unknown is not zero" contract. A correct fix needs a separate provenance channel that records only what a provider actually asserted.
Activity
coderabbitai commentedon Aug 15, 2026
🔗 Related PRs
#963 - fix(catalog): preserve provider capabilities on custom models [open]
#965 - fix(catalog): custom model rows inherit provider reasoning metadata [open]
#1028 - fix(catalog): routed models never inherit the native template's context window (
#992) [merged]#1212 - feat(codex): converge account picker catalogs [merged]
#1435 - fix(catalog): apply providerContextCaps.openai to native OpenAI rows [merged]
📝 Issue Planner
Check the box below or use the
@coderabbitai plancommand to generate an implementation plan and prompts that you can use with your favorite coding assistant.🧪 Issue enrichment is currently in open beta.
To disable automatic issue enrichment, add the following to your
.coderabbit.yaml:💬 Have feedback or questions? Drop into our discord!
fix(routing): source capability evidence from explicit catalog proven…
Wibias commentedon Aug 16, 2026
Fixed by #1799
fix(devin): preserve the catalog image-support flag as a tri-state (#…
feat(devin): propagate catalog supportsImages to the advertised catal…
fix(routing): source capability evidence from explicit catalog proven…
fix(devin): preserve the catalog image-support flag as a tri-state (l…
feat(devin): propagate catalog supportsImages to the advertised catal…