Skip to content

[Bug] Upgrade regenerates read-only openclaw.json and silently overrides user's model config via merge precedence #1869

@nv-ddave

Description

@nv-ddave

Description

After running curl -fsSL https://www.nvidia.com/nemoclaw.sh | bash to upgrade NemoClaw (e.g., to v0.0.15), the read-only config at /sandbox/.openclaw/openclaw.json is regenerated with Nemotron as the default model. This silently overrides the user's custom model selection in the writable config at /sandbox/.openclaw-data/openclaw.json due to a merge precedence issue.

Steps to Reproduce

  1. Configure Claude Opus (or any non-Nemotron model) in the writable config:
    // /sandbox/.openclaw-data/openclaw.json
    {
      "agents": {
        "defaults": {
          "model": "inference/azure/anthropic/claude-opus-4-6"
        }
      }
    }
  2. Verify the agent uses Claude Opus (check sessions.json after a run)
  3. Run curl -fsSL https://www.nvidia.com/nemoclaw.sh | bash to upgrade
  4. Run the agent again
  5. Check sessions.json — the agent now uses nvidia/nemotron-3-super-120b-a12b instead of Claude Opus

Root Cause

The upgrade regenerates the read-only config with:

{
  "agents": {
    "defaults": {
      "model": {"primary": "inference/nvidia/nemotron-3-super-120b-a12b"}
    }
  }
}

The writable config uses "model": "string-value" (flat string), while the regenerated read-only uses "model": {"primary": "..."} (nested object). During mode: "merge", the object form takes precedence over the string form, so the read-only config wins — even though the writable config is supposed to override it.

Expected Behavior

The writable config (/sandbox/.openclaw-data/openclaw.json) should always take precedence over the read-only config (/sandbox/.openclaw/openclaw.json) for the agents.defaults.model field, regardless of whether the value is a string or object.

Workaround

Change the writable config to use the same object format as the read-only:

{
  "agents": {
    "defaults": {
      "model": {"primary": "inference/azure/anthropic/claude-opus-4-6"}
    }
  }
}

This survives future upgrades because both configs use the same key structure and the writable wins the merge.

Impact

  • Users who customized their model to Claude, GPT-4, or other non-Nemotron models get silently downgraded after upgrade
  • No warning or log message indicates the model changed
  • The maxTokens also reverts to 4096 (Nemotron default), which causes tool call truncation for models that support larger output windows
  • Debugging this requires reading sessions.json — not obvious to most users

Environment

  • NemoClaw v0.0.15
  • OpenShell v0.0.28 (m-dev)
  • DGX Spark (aarch64, Ubuntu)
  • Config merge mode: "mode": "merge"

Suggested Fix

Option A: The merge logic should treat the writable config as authoritative for agents.defaults.model regardless of value type (string vs object).

Option B: The upgrade script should detect an existing writable config with a custom model and either (a) preserve it by not regenerating conflicting keys in the read-only config, or (b) warn the user that the model default was reset.

Option C: Log a warning at agent startup when the resolved model differs from what the writable config specifies.

Metadata

Metadata

Assignees

Labels

area: cliCommand line interface, flags, terminal UX, or outputarea: installInstall, setup, prerequisites, or uninstall flowarea: onboardingOnboarding FSM, provider setup, sandbox launch, or first-run flowplatform: wslAffects Windows Subsystem for Linux

Type

No fields configured for Bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions