Last updated

Codex Router Not Working? Troubleshooting & Fixes

Most Codex Router problems have a small set of causes: a missing credential, a disabled provider, a stale catalog, a stopped background service, or a configuration written by a different checkout. This page is the index of those failures and their fixes, adapted from the repository’s docs/TROUBLESHOOTING.md.

Start here: the doctor command

Every troubleshooting session begins the same way:

./bin/model-router codex doctor

Every FAIL line includes a targeted fix. To rebuild only repository-managed files, config and service state:

./bin/model-router codex doctor --fix

If a recognized older Kimi router is reported, add the migration flag:

./bin/model-router codex doctor --fix --migrate-known

Neither command prints credential values, and repair refuses unknown router owners. See the doctor deep dive for what each check covers.

Common issues and fixes

External models are missing from the picker

The intended provider must report both SHOW and ready. Run ./bin/providers, ./bin/refresh-catalog and ./bin/doctor, then fully quit Codex, reopen it, and create a new task — closing only a window does not reload model_catalog_json. Full steps: models missing from the picker.

Routed model agents are missing

Pulling main only updates the source checkout. Apply it to the per-user install and verify the generated custom agents:

./bin/model-router codex update
./bin/model-router codex doctor

The doctor should report OK for Routed model agents; if not, run doctor --fix and restart Codex.

State directory belongs to another checkout

If doctor reports a state ownership failure, you are running from a clone that did not perform the install. Repair through the owning checkout with ./bin/model-router codex doctor --fix. It transfers ownership to the current checkout only when the recorded owner is gone, or when you set MODEL_ROUTER_ALLOW_FOREIGN_STATE=1.

Kimi OAuth is not ready

kimi login
./bin/model-router codex providers enable kimi-oauth
./bin/model-router codex doctor

The router reads the official Kimi CLI credential and refreshes it under a cross-process lock. Do not copy the OAuth token anywhere else.

Windows blocks the Grok OAuth CLI

If grok --version fails with spawn UNKNOWN, “An Application Control policy has blocked this file,” or a Smart App Control notification, use the grok-api provider with an xAI API key instead. See the Windows guide for the exact commands.

An API key is missing or invalid

Re-run the hidden set prompt and check status:

./bin/model-router codex provider-key deepseek set
./bin/model-router codex provider-key deepseek status

Confirm the key belongs to the named system: Kimi OAuth, Kimi Platform, DeepSeek, Anthropic, Alibaba plan and Z.ai coding keys are all separate, non-interchangeable credentials.

A provider changed its model IDs

Compare the provider’s official model-list endpoint with the registry:

./bin/discover-models deepseek

Discovery is read-only. To use a newly discovered model locally before a registry release, curate it for your machine with ./bin/curate-models deepseek.

A routed slug fails with unrouted_model

The picker may have been rebuilt after a model was added or renamed while the background router still has the old registry in memory. Restart the service with ./bin/control service restart, then rerun doctor. If doctor reports a skipped user model, correct or remove that local curation entry. The router now fails an unknown provider/model slug locally instead of accidentally sending the prompt to ChatGPT as if it were a native model.

Old chatgpt-web/* models stopped loading

The unofficial ChatGPT Web browser-automation provider was removed because using it risked suspension or permanent loss of the operator’s OpenAI account. Stop using those routes and remove every stale curated slug with ./bin/curate-models chatgpt-web --remove <slug>. After updating, stale rows are skipped safely rather than routed, but remain in user-models.json until you remove them.

Native GPT models stopped working

Temporarily return Codex to its native base URL:

./bin/model-router codex disable

This removes only the marked block and current service; it preserves the selected model, profiles, provider credentials and ChatGPT login. If native models work again, inspect router health and create a support bundle.

Another process owns ports 4200–4203

lsof -nP -iTCP:4200 -iTCP:4201 -iTCP:4202 -iTCP:4203 -sTCP:LISTEN

Do not kill the process until its owner and purpose are known. The installer migrates only recognized earlier repository services and otherwise stops with a conflict.

The background service is stopped

launchctl print "gui/$(id -u)/io.github.codex-router"
./bin/model-router codex doctor --fix

Linux uses systemctl --user status codex-router.service; Windows uses Get-ScheduledTask -TaskName "Codex Router". Keep the repository at the absolute path used during installation, and rerun setup from the new path if it was moved.

On Windows, start and restart now check that the scheduled task actually exists before calling schtasks. If the task is missing you get a message naming the task plus service.mjs install and doctor --fix, instead of schtasks.exe’s own error and a false {"state":"running"}. Nothing is mutated on the way out.

A first install timed out after 300 seconds

A large catalog can make LiteLLM’s first cold start exceed the installer’s five-minute health wait even when the service and launchers were installed correctly. Current main reports retryable exit code 75 (EX_TEMPFAIL) and preserves the service, launchers and client configuration instead of uninstalling them. Follow the platform-specific service check above, wait for the service to become healthy, then run ./bin/model-router codex doctor --fix. A confirmed crash loop or missing launcher is still treated as a failed installation and rolled back.

An update failed

./bin/model-router codex rollback

Updates refuse edits to tracked files (untracked files never block an update; --force discards tracked edits), non-main development branches and unknown origin URLs rather than overwriting local work. Legacy migration rollback is separate: ./bin/migrate rollback.

A session ran past the context window instead of compacting

Codex decides when to auto-compact from the input_tokens each response reports. A provider that answers a large prompt with input_tokens: 0 leaves that counter flat, so the context bar looks nearly empty right up to the point the provider rejects the turn. The router substitutes an estimate of the prompt it just sent when — and only when — a routed response explicitly reports zero prompt tokens for a request that plainly carried a large one.

Substitutions are recorded rather than hidden: the usage event keeps the provider’s own numbers and adds estimatedInputTokens, and the router logs estimated-input-tokens=<count> on that turn. Count them in the state directory’s usage-events.jsonl:

grep -c estimatedInputTokens "$CODEX_HOME/codex-router/usage-events.jsonl"

Report zero-token responses to the provider — only they can fix the source. To see the provider’s own numbers in Codex again, set CODEX_ROUTER_ZERO_INPUT_ESTIMATE=0 in the service environment.

Responses WebSocket does not connect

Current releases accept the Responses WebSocket v2 upgrade. A 401 usually means Codex still has a stale managed URL: run ./bin/doctor --fix, fully quit Codex, then reopen it. A 426 carrying the supported OpenAI-Beta: responses_websockets=2026-02-06 hint means the attempted WebSocket contract did not match and Codex will fall back to HTTP; provider errors still arrive as normal Responses error events.

Voice Mode reports an unsupported /v1/live route

Codex Voice uses native realtime endpoints that are separate from the Responses API. Run ./bin/enable again after updating, fully quit Codex, and reopen it so the managed realtime overrides take effect.

Uninstall retained files

This is intentional. ./bin/uninstall removes only the active integration and background service; the state directory may contain credentials, logs, catalog caches, install history and rollback snapshots. Inspect it manually before deleting anything.

Create a support bundle

./bin/support-bundle

The generated mode-600 JSON includes versions, doctor checks, service state, provider presence, config ownership and file metadata—it excludes credential values, prompts, responses and log contents. The legacy --include-logs option is now a deprecated no-op because old logs can contain credentials that were later rotated or deleted. The tool never uploads a bundle automatically.

Still stuck?

Open an issue on the Codex Router repository and attach the redacted support bundle. Include the doctor output and the exact error text, but never paste a complete managed base URL or any credential.