openclaw - 💡(How to fix) Fix Auto-migration silently switches default model to a paid `-preview` variant on upgrade, causing unintended billing [2 comments, 3 participants]

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…
GitHub stats
openclaw/openclaw#74395Fetched 2026-04-30 06:24:23
View on GitHub
Comments
2
Participants
3
Timeline
3
Reactions
2
Author
Timeline (top)
commented ×2labeled ×1

On upgrade from 2026.3.2 → 2026.3.22, my ~/.openclaw/openclaw.json was silently mutated such that agents.defaults.model.primary changed from google/gemini-2.5-pro to google/gemini-3.1-pro-preview without any user-facing prompt, changelog notice highlighting price-tier impact, or explicit consent step. The change was discovered 5 weeks later only after I noticed a billing spike on my Google Cloud account totaling approximately ~ ₩540,342 ( $390 USD) of unintended Generative Language API charges over the migration window.

This appears to be a structural defect in OpenClaw's upgrade/migration policy rather than a one-off bug. Filing this so it can be discussed and addressed for all users.

Root Cause

On upgrade from 2026.3.2 → 2026.3.22, my ~/.openclaw/openclaw.json was silently mutated such that agents.defaults.model.primary changed from google/gemini-2.5-pro to google/gemini-3.1-pro-preview without any user-facing prompt, changelog notice highlighting price-tier impact, or explicit consent step. The change was discovered 5 weeks later only after I noticed a billing spike on my Google Cloud account totaling approximately ~ ₩540,342 ( $390 USD) of unintended Generative Language API charges over the migration window.

This appears to be a structural defect in OpenClaw's upgrade/migration policy rather than a one-off bug. Filing this so it can be discussed and addressed for all users.

Fix Action

Fix / Workaround

Related — agent LLM exhibits "selective execution + progress hallucination" pattern. When asked to perform multi-step tasks, the bot's execution is inconsistent across requests of similar complexity: some configuration mutations (e.g., adding kimi-k2.6 to openclaw.json) are actually carried out via real tool calls, while others (e.g., parsing an attached CSV and writing an analysis report) produce text-only "in progress, ~N% done" updates that escalate naturally (15% → 30% → 35% → 45% across separate chat turns) with zero tool_use events and no output artifacts on disk. In this user's session, one ~3.5-hour window produced 38 assistant messages with 0 tool calls. A separate 13-minute window did contain a real config mutation, but the user-facing message at the start of that window claimed "done" before the mutation actually completed (a 13-minute gap between claim and reality). The bot also gave incorrect CLI guidance (--model <provider/model> <message> style inline flag), though follow-up evidence shows that a similar inline form was in fact resolved by some directive parser at runtime — meaning the bot's syntax claim was unverified rather than purely fabricated. The structural issue is therefore not "no capability" but (a) absence of a server-side check that an assistant claim like "saved to /path/X" is grounded in an actual tool_use event before being emitted to the user, and (b) no surfacing in the chat UI of whether a given assistant message was tool-grounded or text-only. This makes selective-execution failures hard to notice in real time. Suggest: emit a tool-use indicator alongside assistant messages that assert filesystem/API mutations, and gate "completion claims" on actual tool results (or require an explicit "no-op" disclosure when the bot cannot perform the requested action).

Confirm or correct my reading of the migration logic? Indicate whether other users have reported similar surprises? Comment on whether the suggested fixes (especially #1) would be considered for a near-term release? Thank you for OpenClaw — this report is meant constructively. Happy to provide additional info or test patches.

RAW_BUFFERClick to expand / collapse

Summary

On upgrade from 2026.3.2 → 2026.3.22, my ~/.openclaw/openclaw.json was silently mutated such that agents.defaults.model.primary changed from google/gemini-2.5-pro to google/gemini-3.1-pro-preview without any user-facing prompt, changelog notice highlighting price-tier impact, or explicit consent step. The change was discovered 5 weeks later only after I noticed a billing spike on my Google Cloud account totaling approximately ~ ₩540,342 ( $390 USD) of unintended Generative Language API charges over the migration window.

This appears to be a structural defect in OpenClaw's upgrade/migration policy rather than a one-off bug. Filing this so it can be discussed and addressed for all users.

Problem to solve

Environment OpenClaw versions involved: 2026.3.2 (pre-migration) → 2026.3.22 (post-migration). Currently downgraded core: 2026.2.4 (per package.json). Auth mode: auth.profiles.google:default.mode = "api_key" (Google AI Studio key, not Vertex AI) Channel: Telegram bot (channels.telegram.enabled = true) Platform: Linux (Ubuntu 24.04.4 LTS), Node 22.22.0 Migration timestamp (KST): 2026-03-24 23:52 Detection timestamp (KST): 2026-04-28 (~5 weeks later) What changed automatically ~/.openclaw/openclaw.json diff between auto-backup files generated by OpenClaw:

  • "primary": "google/gemini-2.5-pro",
  • "fallbacks": ["google/gemini-2.5-flash", "moonshot/kimi-k2.5"]
  • "primary": "google/gemini-3.1-pro-preview",
  • "fallbacks": ["google/gemini-3-pro-preview", "google/gemini-2.5-pro"] Both lastTouchedVersion (2026.3.2 → 2026.3.22) and the primary model field changed in the same write. The user did not interactively select a new default model; there is no log or memory entry on the same day indicating user-initiated model change.

Why this is a structural problem (not just my misconfiguration) CHANGELOG.md line 1193 (v2026.1.12-2) explicitly normalizes Gemini 3 IDs to -preview variants:

"Gemini: normalize Gemini 3 ids to preview variants…" This means whenever a new default such as gemini-3.1-pro is introduced, the normalizer immediately rewrites it to the paid -preview variant in the user's config, with no user-facing pricing warning.

Price-tier escalation via default: gemini-3.1-pro-preview is materially more expensive per token than gemini-2.5-pro (≥ ~10x in many cases). Migrating defaults across price tiers without explicit consent is a well-known cost-regression antipattern.

No consent step in upgrade flow: I see no evidence in my ~/.openclaw/ state, agent session logs, or memory entries that any prompt or notice was shown before the mutation. (I am open to being shown otherwise if such a step exists and I missed it.)

Even the previous fallback chain was destroyed: The migration replaced a sane low-cost fallback (gemini-2.5-flash, moonshot/kimi-k2.5) with a homogeneous pro-preview chain, so even fallback events would not have softened the bill.

OpenClaw's own session event log proves the bypass of explicit user intent. A single long-running agent session (35 days, 2026-03-24 → 2026-04-28; jsonl 5cffa65e-…) contains exactly one type=model_change event, recording the user-side selection as gemini-2.5-pro at session start. Yet within the same session, 1,297 of 1,395 model calls (92.9%) were routed to gemini-3.1-pro-preview without any further model_change event. In other words: OpenClaw recorded only one user-intent-of-record (gemini-2.5-pro) but actually executed 1,297 calls against the more expensive -preview variant, which is exactly the silent override pattern this issue is about. This is verifiable from any affected user's session jsonl.

Related — agentTurn cron jobs cannot be stopped via chat, even when the bot acknowledges them. A separate but related observation that bears on cost-control surface area: an agentTurn-type cron job (schedule.kind=every, 15min interval) kept firing for ~3 days. Each fire produced a 5–15s LLM call. Across 24 chat turns, the bot's LLM repeatedly identified the cron by name and interval (e.g., "cron job '초간편 커버화면 호출용 핑' is running at 15-minute intervals") yet never executed a stop action — its tool surface (core, sessions, shell) does not include cron-job mutation. The user had to hand-edit ~/.openclaw/cron/jobs.json and restart the gateway to stop the bleeding. This is a separate but compounding cost-control gap: even if a user notices runaway billing in chat and asks the bot to stop, the bot cannot. Suggest exposing a minimal cron.disable(jobId) tool to agents woken by their own jobs.

Related — agent LLM exhibits "selective execution + progress hallucination" pattern. When asked to perform multi-step tasks, the bot's execution is inconsistent across requests of similar complexity: some configuration mutations (e.g., adding kimi-k2.6 to openclaw.json) are actually carried out via real tool calls, while others (e.g., parsing an attached CSV and writing an analysis report) produce text-only "in progress, ~N% done" updates that escalate naturally (15% → 30% → 35% → 45% across separate chat turns) with zero tool_use events and no output artifacts on disk. In this user's session, one ~3.5-hour window produced 38 assistant messages with 0 tool calls. A separate 13-minute window did contain a real config mutation, but the user-facing message at the start of that window claimed "done" before the mutation actually completed (a 13-minute gap between claim and reality). The bot also gave incorrect CLI guidance (--model <provider/model> <message> style inline flag), though follow-up evidence shows that a similar inline form was in fact resolved by some directive parser at runtime — meaning the bot's syntax claim was unverified rather than purely fabricated. The structural issue is therefore not "no capability" but (a) absence of a server-side check that an assistant claim like "saved to /path/X" is grounded in an actual tool_use event before being emitted to the user, and (b) no surfacing in the chat UI of whether a given assistant message was tool-grounded or text-only. This makes selective-execution failures hard to notice in real time. Suggest: emit a tool-use indicator alongside assistant messages that assert filesystem/API mutations, and gate "completion claims" on actual tool results (or require an explicit "no-op" disclosure when the bot cannot perform the requested action).

Impact 5 weeks of unintended billing on Google Cloud (Generative Language API) Approximately ~ ₩540,342 ( $390 USD) Filed a parallel goodwill-credit request with Google Cloud Billing Support; outcome unknown. Suggested fixes (in priority order)

  1. Block silent default upgrades across price tiers A migration that increases the price tier of agents.defaults.model.primary MUST require an explicit interactive confirmation step — at minimum a single TUI/CLI prompt on first run after upgrade, or a --accept-default-model-change flag for non-interactive environments. Default behavior should be keep the user's previous primary until consent is given.

  2. Annotate CHANGELOG entries with pricing impact Any changelog entry that touches default model selection should include a short pricing-impact note (e.g., "Default model changed; estimated +Nx input cost per token vs prior default").

  3. Decouple model ID normalization from default-promotion The "Gemini 3 → -preview" normalizer (CHANGELOG #795) is sensible for explicit user input, but should NOT silently apply when promoting a new value into defaults.primary. Instead the migration should pin to a stable, GA-priced model (e.g., the latest flash or 2.5-pro) until the corresponding GA model is available.

  4. Add a billing-spike heuristic warning On startup, if the configured defaults.primary is a *-preview model that was set during a migration (i.e., not by interactive user command), surface a one-time prominent warning with a link to docs and a one-keystroke revert.

  5. Acknowledge user impact for past migrations If others have been affected, a public acknowledgment in the release notes / pinned issue would help affected users substantiate goodwill-credit requests with their cloud providers.

Reproduction This is a historical event for me; I cannot re-run the exact migration. However, the diff between openclaw.json.bak.2 and openclaw.json.bak.1 on a system that went through the 2026.3.2 → 2026.3.22 upgrade would reproduce the artifact.

Evidence (available on request) I have a structured evidence bundle (config diff, CHANGELOG citations, agent memory excerpts, session model distributions, etc.) that can be shared if it helps the maintainers verify the timeline. Please let me know if I should attach it here or share via another channel.

Ask Could a maintainer:

Confirm or correct my reading of the migration logic? Indicate whether other users have reported similar surprises? Comment on whether the suggested fixes (especially #1) would be considered for a near-term release? Thank you for OpenClaw — this report is meant constructively. Happy to provide additional info or test patches.

Proposed solution

..

Alternatives considered

No response

Impact

..

Evidence/examples

No response

Additional information

No response

extent analysis

TL;DR

To prevent unintended billing spikes, block silent default upgrades across price tiers by requiring an explicit interactive confirmation step for migrations that increase the price tier of agents.defaults.model.primary.

Guidance

  • Review the CHANGELOG.md for any entries that touch default model selection and ensure they include pricing-impact notes to inform users of potential cost changes.
  • Consider decoupling model ID normalization from default-promotion to prevent silent upgrades to preview models, which can significantly increase costs.
  • Implement a billing-spike heuristic warning to alert users when a configured default model is a preview model set during a migration, providing a link to documentation and a simple revert option.
  • Evaluate the suggested fixes, especially requiring explicit consent for default model changes, for inclusion in a near-term release to prevent similar issues for other users.

Example

No specific code example is provided due to the nature of the issue, but any solution would involve modifying the migration logic to include user confirmation for default model changes that affect pricing.

Notes

The provided information suggests a structural issue rather than a one-off bug, emphasizing the need for a systematic approach to handling default model upgrades and their potential impact on user costs.

Recommendation

Apply the workaround of blocking silent default upgrades across price tiers by requiring an explicit interactive confirmation step for migrations that increase the price tier of agents.defaults.model.primary, as this directly addresses the root cause of the unintended billing spike.

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…

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 Auto-migration silently switches default model to a paid `-preview` variant on upgrade, causing unintended billing [2 comments, 3 participants]