Skip to content

[Bug]: manual opencode-go modelContextWindows entries are reset after update #1409

Closed

Description

@RanceLee233

Client or integration

Codex App

Area

Catalog / models / config persistence

Current status

This issue remains open, but its scope is narrower than the original report suggested.

Current dev contains config-rebase work that fixed at least one confirmed management/save path which could lose provider configuration. However, the broader whole-document writer fix attempted in #1462 was closed without merge, and the original upgrade + later unrelated-write reproduction has not been proven fully covered.

Do not close this issue based only on the presence of the newer rebase-on-save machinery. The close condition is that the original user override survives the actual lifecycle described below, including upgrade/restart and an unrelated later save.

The architectural ambiguity behind stale-config rebasing is tracked separately in #1478.

Problem

An explicit user value under:

providers.opencode-go.modelContextWindows

was removed after upgrading and then performing a later unrelated config/provider write. The provider fell back to registry-seeded context metadata.

Registry defaults may seed missing values, but they must not overwrite or delete explicit user overrides.

Original reproduction

  1. Configure:
{
  "providers": {
    "opencode-go": {
      "modelContextWindows": {
        "deepseek-v4-flash": 900000
      }
    }
  }
}
  1. Run OpenCodex 2.11.0 and verify the override is effective.
  2. Upgrade to 2.11.1 and restart the daemon/app.
  3. Perform an unrelated provider/config write.
  4. Inspect config.json.
  5. The explicit deepseek-v4-flash entry was gone and opencode-go.modelContextWindows contained only registry-seeded values.
  6. The generated catalog then fell back to its default context window.

The separate deepseek provider's context-window configuration was not affected in the original report.

Required behavior

  • Explicit user modelContextWindows values survive upgrade and restart.
  • Registry defaults only fill genuinely missing values.
  • An unrelated management/API/provider save must not remove an override that the writer did not intend to change.
  • A deliberate deletion of an override must still remain possible and must not be resurrected by a rebase.
  • Concurrent or independently loaded config writers must not silently erase unseen keys.

The last two requirements interact with the provenance problem in #1478. Fixing one by blindly treating every absent key as deletion, or every absent key as ignorance, is not sufficient.

Acceptance test

A regression should exercise the complete lifecycle rather than only a single helper:

seed explicit opencode-go modelContextWindows override
        ↓
load/start server
        ↓
perform registry/default reconciliation if applicable
        ↓
perform an unrelated management/config write
        ↓
reload from disk
        ↓
explicit override is still present and effective

Also cover deliberate deletion so the persistence fix does not make stale values impossible to remove.

Close condition

Close only when the original lifecycle is covered on current dev by a regression proving both preservation of explicit user overrides and intentional deletion semantics.

Related

Activity

  1. Ingwannu commented on Aug 10, 2026

    @Ingwannu
    Owner

    I checked current dev. src/providers/derive.ts:405 seeds modelContextWindows only when the entire user map is absent; src/router.ts:273-275 fills registry values beneath user entries; and src/server/management/provider-routes.ts:185-204 merges individual keys. None of those paths should replace the explicit deepseek-v4-flash value with the kimi-k3 registry seed.

    The timing in this report, where a later unrelated full-config write makes the reset visible, matches the stale whole-document writer still tracked in #1273. The current sequence does not yet prove that it is the only cause, however. Please provide the exact order and redacted before/after snippets: which OCX or proxy processes were alive, whether the 900000 value was edited while the proxy was already running, which CLI or Dashboard action performed the unrelated write, and whether any restart happened between those steps. Config-file mtime and relevant mutation-generation log lines would also help.

    Keeping this open separately until we can determine whether #1273 fully explains the write or whether the update path directly rewrites this field.

  2. lidge-jun commented on Aug 12, 2026

    @lidge-jun
    Owner

    A real data-loss path in this area is fixed on dev by #1535, merged as b310d1826a2793c7cb1b9338f985c8c553e723b3. This does not close the issue — see the attribution note below.

    What was confirmed and fixed: POST /api/providers lost hand-edited context windows on an overwrite. The dashboard's provider payload type has no member for contextWindow or modelContextWindows, so the add/edit form structurally cannot send them; registry enrichment then filled the absent fields from the seed and the stored row became the seed. For opencode-go that seed is exactly {"kimi-k3": 262144} — precisely what you found in place of your deepseek-v4-flash entry.

    Both fields are now carried across an overwrite, following the precedent already in that function for apiKeyPool and modelCosts: the form does not send them, so absence must mean "not carried", never "the user deleted it". Deletion stays an explicit null through PATCH.

    Why this is not enough to close the report. The reproduction I can demonstrate is a duplicate-name POST through the Add Provider modal. Your sequence was an upgrade, a daemon restart, and a later unrelated full-config write — and the dashboard's normal editing surfaces use PATCH, which already merged per key and preserved unmentioned entries. So the fixed path may not be the one you hit, and @Ingwannu's earlier note pointing at the stale whole-document writer in #1273 remains the leading hypothesis.

    If you can still reproduce on a build containing b310d1826, the most useful thing would be the exact order: which OCX or proxy processes were alive, whether the value was edited while the proxy was running, which CLI or Dashboard action performed the unrelated write, and whether a restart happened between those steps.

    Verification at the merged head: tsc exit 0; tests/management-provider-validation.test.ts 60 pass / 0 fail; 60-file provider/config/management sweep 1023 pass / 0 fail; full suite 11,316 pass / 0 fail; 23 CI checks green including all Linux shards and macOS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething 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