openclaw - 💡(How to fix) Fix [Bug]: sessions.patch model:null leaves liveModelSwitchPending=true on disk; produces ghost model labels in /model after provider removal

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

sessions.patch with model: null returns success and clears modelOverride, providerOverride, and modelOverrideSource from the session entry, but leaves liveModelSwitchPending: true on disk. The orphan flag causes downstream resolvers (e.g. /model rendering) to reconstruct a ghost selection from the session's .jsonl trajectory, which produces nonsensical model labels in chat when the originally-pinned model/provider no longer exists in config.

This is distinct from #69951 (override silently ignored), #77322 (session.model cache survives /new), and #73090 (modelProvider metadata not normalized for CLI runtimes).

Root Cause

sessions.patch with model: null returns success and clears modelOverride, providerOverride, and modelOverrideSource from the session entry, but leaves liveModelSwitchPending: true on disk. The orphan flag causes downstream resolvers (e.g. /model rendering) to reconstruct a ghost selection from the session's .jsonl trajectory, which produces nonsensical model labels in chat when the originally-pinned model/provider no longer exists in config.

This is distinct from #69951 (override silently ignored), #77322 (session.model cache survives /new), and #73090 (modelProvider metadata not normalized for CLI runtimes).

Fix Action

Fix / Workaround

sessions.patch with model: null returns success and clears modelOverride, providerOverride, and modelOverrideSource from the session entry, but leaves liveModelSwitchPending: true on disk. The orphan flag causes downstream resolvers (e.g. /model rendering) to reconstruct a ghost selection from the session's .jsonl trajectory, which produces nonsensical model labels in chat when the originally-pinned model/provider no longer exists in config.

T1: pin a model

openclaw gateway call sessions.patch --params
'{"key":"agent:main:main","model":"openai/gpt-5.5"}'

T3: clear pin

openclaw gateway call sessions.patch --params
'{"key":"agent:main:main","model":null}'

Code Example

SK='{"key":"agent:main:main"}'

# T0: confirm clean state
python3 -c "
import json
s = json.load(open('$HOME/.openclaw/agents/main/sessions/sessions.json'))['agent:main:main']
for k in ('modelOverride','providerOverride','modelOverrideSource','liveModelSwitchPending'):
    print(f'{k}: {s.get(k, \"<unset>\")}')
"

# T1: pin a model
openclaw gateway call sessions.patch --params \
  '{"key":"agent:main:main","model":"openai/gpt-5.5"}'

# T2: confirm all 4 fields are set
python3 -c "... (same as T0)"
# Output:
#   modelOverride: gpt-5.5
#   providerOverride: openai
#   modelOverrideSource: user
#   liveModelSwitchPending: True

# T3: clear pin
openclaw gateway call sessions.patch --params \
  '{"key":"agent:main:main","model":null}'

# T4: re-check fields
python3 -c "... (same as T0)"

---

modelOverride: <unset>          ✓ cleared
providerOverride: <unset>       ✓ cleared
modelOverrideSource: <unset>    ✓ cleared
liveModelSwitchPending: TrueORPHANED

---

Current: openai/qwen-7b
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug / partial state cleanup

Beta release blocker

No

Summary

sessions.patch with model: null returns success and clears modelOverride, providerOverride, and modelOverrideSource from the session entry, but leaves liveModelSwitchPending: true on disk. The orphan flag causes downstream resolvers (e.g. /model rendering) to reconstruct a ghost selection from the session's .jsonl trajectory, which produces nonsensical model labels in chat when the originally-pinned model/provider no longer exists in config.

This is distinct from #69951 (override silently ignored), #77322 (session.model cache survives /new), and #73090 (modelProvider metadata not normalized for CLI runtimes).

Environment

  • OpenClaw: 2026.5.12 (f066dd2)
  • Install: npm global (/usr/lib/node_modules/openclaw)
  • OS: Zorin OS 18.1 (Linux 6.17, x86_64)
  • Gateway: local, systemd --user
  • Channel where ghost label was observed: Telegram DM

Steps to reproduce

Pure gateway-call repro, no UI required.

SK='{"key":"agent:main:main"}'

# T0: confirm clean state
python3 -c "
import json
s = json.load(open('$HOME/.openclaw/agents/main/sessions/sessions.json'))['agent:main:main']
for k in ('modelOverride','providerOverride','modelOverrideSource','liveModelSwitchPending'):
    print(f'{k}: {s.get(k, \"<unset>\")}')
"

# T1: pin a model
openclaw gateway call sessions.patch --params \
  '{"key":"agent:main:main","model":"openai/gpt-5.5"}'

# T2: confirm all 4 fields are set
python3 -c "... (same as T0)"
# Output:
#   modelOverride: gpt-5.5
#   providerOverride: openai
#   modelOverrideSource: user
#   liveModelSwitchPending: True

# T3: clear pin
openclaw gateway call sessions.patch --params \
  '{"key":"agent:main:main","model":null}'

# T4: re-check fields
python3 -c "... (same as T0)"

Expected behavior

T4 should show all four fields as <unset>. sessions.patch model:null is the documented way to clear a pinned model and should leave the entry in the same shape as a fresh session.

Actual behavior

T4 output:

modelOverride: <unset>          ✓ cleared
providerOverride: <unset>       ✓ cleared
modelOverrideSource: <unset>    ✓ cleared
liveModelSwitchPending: True    ✗ ORPHANED

The orphan liveModelSwitchPending: true survives indefinitely until either (a) another sessions.patch with a concrete model triggers a successful live switch (which clears it via clearLiveModelSwitchPending), or (b) manual JSON edit.

Observed downstream impact

In my session this morning, the orphan flag manifested when sending /model in Telegram. The handler showed:

Current: openai/qwen-7b

qwen-7b was an alias I had defined hours earlier on a now-removed llm-vps provider. The provider entry and the alias had both been deleted from openclaw.json and the gateway restarted. The only remaining trace was the orphan liveModelSwitchPending: true on agent:main:main. The handler's resolveLiveSessionModelSelection path apparently mined the session's .jsonl trajectory for the most recent /new-style switch, found "qwen-7b" (now an unknown identifier), and fell back to the default provider (openai) to render the bogus openai/qwen-7b label.

Removing liveModelSwitchPending: true manually from the entry, then re-rendering /model, immediately produced the correct Current: openai/gpt-5.

Suggested fix direction

In the same code path that handles sessions.patch with model: null (clearing the pin), also call clearLiveModelSwitchPending for that session key. The function already exists at live-model-switch-CgybHLBX.js (bundled name) and is what model_spawn and live-switch retries use to consume the flag — it should be the canonical drain on explicit-clear as well.

A defensive measure in formatCurrentModelLine / resolveLiveSessionModelSelection (don't synthesize a selection from trajectory when the override fields are unset) would also prevent ghost labels even if the orphan flag persists for unrelated reasons.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

T4 should show all four fields as <unset>. sessions.patch model:null is the documented way to clear a pinned model and should leave the entry in the same shape as a fresh session.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix [Bug]: sessions.patch model:null leaves liveModelSwitchPending=true on disk; produces ghost model labels in /model after provider removal