Skip to content

codex: legacy-config strip removes [model_providers.ucode-databricks] but leaves model_provider dangling → bare codex/desktop app fail with "Model provider not found" #212

Description

@randypitcherii

Symptom

After running ucode codex (or ucode configure) on a machine where an earlier ucode version had deep-merged its provider into the shared ~/.codex/config.toml, every bare codex invocation — including the Codex desktop app, which only reads ~/.codex/config.toml — dies immediately with:

Error: Model provider `ucode-databricks` not found

Root cause

The modern-layout migration removes ucode's provider block from the shared config but leaves the top-level model_provider key that points at it:

  • _remove_legacy_ucode_profile() fires whenever _has_legacy_ucode_entries sees [model_providers.ucode-databricks] in ~/.codex/config.toml.
  • _strip_legacy_ucode_entries() pops profile, profiles.ucode, and model_providers.ucode-databricks — but not the top-level model_provider = "ucode-databricks" selector.

The model_provider key at top level is exactly what older ucode wrote via MANAGED_KEYS (codex.py#L46-L51 — note ["model_provider"] is the first managed key), and it's also what the Codex desktop app persists when the user has been routing through the gateway. After the strip, the config references a provider that no longer exists, and codex refuses to start rather than falling back.

Repro

  1. Start with a ~/.codex/config.toml containing (modern shape, no profile selector — this is what a desktop-app user routing through the gateway has):
    model_provider = "ucode-databricks"
    model = "gpt-5.6-sol"
    
    [model_providers.ucode-databricks]
    name = "Databricks AI Gateway"
    base_url = "https://<workspace>.cloud.databricks.com/ai-gateway/codex/v1"
    wire_api = "responses"
    
    [model_providers.ucode-databricks.auth]
    command = "/Users/<user>/.local/bin/ucode"
    args = ["auth-token", "--host", "https://<workspace>.cloud.databricks.com", "--profile", "DEFAULT"]
    codex exec "say hi" works.
  2. Run ucode codex -- exec "say hi" — works (uses ~/.codex/ucode.config.toml), but as a side effect strips [model_providers.ucode-databricks] from ~/.codex/config.toml, leaving model_provider = "ucode-databricks" dangling.
  3. Run bare codex exec "say hi" again → Error: Model provider 'ucode-databricks' not found. The desktop app is equally broken until the block is re-added by hand.

Observed with ucode v0.1.0 (installed 2026-07-12 from this repo) and Codex 0.143.0-alpha.33 / 0.144.2 on macOS.

Suggested fix

In _strip_legacy_ucode_entries, also pop the top-level selector when it points at the stripped provider:

if doc.get("model_provider") == CODEX_MODEL_PROVIDER_NAME:
    doc.pop("model_provider", None)
    changed = True

(and probably the managed model key alongside it, mirroring MANAGED_KEYS). Alternatively, skip the strip entirely when the file has no profile/profiles.ucode selector — a top-level model_provider + provider block is a working modern config the user may be relying on for the desktop app, not legacy cruft.

Related: #148 covers ucode revert not undoing the legacy in-place edits; this is the inverse problem — the automatic cleanup undoing them partially and leaving the config broken.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions