← Back to PRs

#20275: fix(cli): include primary model in allowlist when adding fallbacks

by MFS-code open 2026-02-18 18:38 View on GitHub →
commands size: XS
## Summary - **Problem:** `openclaw models fallbacks add <model>` populates `agents.defaults.models` (the model allowlist) with only the fallback model, omitting the currently configured primary model. This silently blocks the primary model for all sessions and cron jobs with `model not allowed`. - **Why it matters:** 100% reproducible on every `fallbacks add` invocation; silently breaks all chat sessions and cron jobs using the primary model with no warning from the CLI. - **What changed:** `addFallbackCommand` now resolves the current primary model from `cfg.agents.defaults.[key].primary` and ensures it is included in the `models` allowlist alongside the new fallback. - **What did NOT change (scope boundary):** Fallback resolution, model selection, `removeFallbackCommand`, `clearFallbacksCommand`, image model fallbacks logic, config schema. ## Change Type (select all) - [x] Bug fix - [ ] Feature - [ ] Refactor - [ ] Docs - [ ] Security hardening - [ ] Chore/infra ## Scope (select all touched areas) - [ ] Gateway / orchestration - [ ] Skills / tool execution - [ ] Auth / tokens - [ ] Memory / storage - [ ] Integrations - [ ] API / contracts - [x] UI / DX - [ ] CI/CD / infra ## Linked Issue/PR - Closes #20265 ## User-visible / Behavior Changes - After running `openclaw models fallbacks add <model>`, the primary model now remains in `Configured models` and continues to work. Previously it was silently excluded from the allowlist and blocked. ## Security Impact (required) - New permissions/capabilities? `No` - Secrets/tokens handling changed? `No` - New/changed network calls? `No` - Command/tool execution surface changed? `No` - Data access scope changed? `No` ## Repro + Verification ### Environment - OS: macOS 15 (Sequoia) - Runtime/container: Node.js - Model/provider: Any (reproduced with anthropic/claude-opus-4-6 + openai/o3) - Integration/channel (if any): N/A - Relevant config (redacted): Clean config with primary model set, no fallbacks ### Steps 1. Start with a clean config: primary model is `anthropic/claude-opus-4-6`, no fallbacks, no `agents.defaults.models` 2. Run `openclaw models fallbacks add openai/o3` 3. Check `openclaw models status` ### Expected - `Configured models` includes both `anthropic/claude-opus-4-6` and `openai/o3` ### Actual (before fix) - `Configured models (1): openai/o3` — primary model excluded, all sessions fail with `model not allowed: anthropic/claude-opus-4-6` ## Evidence - [x] Failing test/log before + passing after - [x] Trace/log snippets - [ ] Screenshot/recording - [ ] Perf numbers (if relevant) `pnpm build` — 0 errors `pnpm check` — 0 warnings, 0 errors `pnpm test src/commands/models` — 25/25 tests pass Verified end-to-end: `fallbacks add` now produces `Configured models (2)` including both primary and fallback. ## Human Verification (required) - **Verified scenarios:** Ran `openclaw models fallbacks add` with a configured primary model; confirmed both primary and fallback appear in `Configured models` after the command. Sent messages using the primary model — no `model not allowed` error. - **Edge cases checked:** Primary model already in allowlist (no duplicate); no primary set (no-op, guard skips); primary same as fallback being added (both paths add it, no conflict). ## Compatibility / Migration - Backward compatible? `Yes` - Config/env changes? `No` - Migration needed? `No` ## Failure Recovery (if this breaks) - How to disable/revert this change quickly: Revert the single commit - Files/config to restore: `src/commands/models/fallbacks-shared.ts` - Known bad symptoms reviewers should watch for: Duplicate model entries in `agents.defaults.models` (shouldn't happen due to `if (!nextModels[primaryKey])` guard) ## Risks and Mitigations - Risk: `resolveModelTarget` throws if the stored primary string is malformed - Mitigation: Only called when `primaryRaw` is a non-empty string (already stored by a prior successful `models set` command); same function is used throughout the codebase for model resolution --- **AI-assisted PR (per CONTRIBUTING.md guidelines):** - [x] Marked as AI-assisted (Claude) - [x] Degree of testing: fully tested (`pnpm build && pnpm check && pnpm test`) + manual end-to-end verification - [x] I understand what the code does: the fix adds the current primary model to the `agents.defaults.models` allowlist when `addFallbackCommand` writes a new fallback entry, preventing the primary from being silently blocked Made with [Cursor](https://cursor.com) <!-- greptile_comment --> <h3>Greptile Summary</h3> Fixes a bug where `addFallbackCommand` only added the new fallback model to the `agents.defaults.models` allowlist, omitting the currently configured primary model. This caused the primary model to be silently blocked with a `model not allowed` error for all sessions and cron jobs after running `fallbacks add`. - The fix resolves the primary model from `cfg.agents.defaults.[key].primary` and adds it to the `nextModels` allowlist alongside the new fallback, following the same `resolveModelTarget`/`modelKey` pattern used elsewhere in the codebase - Includes a guard for missing/empty primary (no-op when no primary is configured) - Change is minimal and well-scoped — only affects the `addFallbackCommand` function in `fallbacks-shared.ts` - Note: the fix does not include a dedicated unit test for the new primary-inclusion behavior; the existing test at `models.set.e2e.test.ts:62` uses a mock without a primary set, so it doesn't exercise the new code path <h3>Confidence Score: 4/5</h3> - This PR is safe to merge — it's a targeted, well-scoped fix that follows existing codebase patterns and addresses a clear bug. - The change is small (13 lines), follows established patterns in the codebase (same type assertions and utility functions), and includes proper guards for edge cases (empty/missing primary). The fix correctly addresses the described bug. Docking one point because no unit test was added for the new code path — the existing test mocks don't exercise the primary-inclusion logic. - No files require special attention. The single changed file (`src/commands/models/fallbacks-shared.ts`) is straightforward. <sub>Last reviewed commit: 1f00264</sub> <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs