#20275: fix(cli): include primary model in allowlist when adding fallbacks
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
#21963: fix(cli): models fallbacks add now includes primary model in allowlist
by ashiabbott · 2026-02-20
91.9%
#23816: fix(agents): model fallback skipped during session overrides and pr...
by ramezgaberiel · 2026-02-22
85.8%
#22064: fix(failover): bypass models allowlist for configured fallback models
by winston-bepresent · 2026-02-20
84.9%
#23033: fix: continue to fallbacks when first fallback throws unclassified ...
by ismsaa · 2026-02-21
83.9%
#11349: fix(agents): do not filter fallback models by models allowlist
by liuxiaopai-ai · 2026-02-07
83.3%
#18697: fix: include forward-compat models in model catalog for allowlist val…
by dmitry-orabey · 2026-02-17
81.6%
#16838: fix: include configured fallbacks in model allowlist
by taw0002 · 2026-02-15
80.7%
#8390: feat: notify user when fallback model is used (#8182)
by Glucksberg · 2026-02-04
80.4%
#21088: fix: sessions_sspawn model override ignored for sub-agents
by Slats24 · 2026-02-19
79.9%
#23738: feat(fallback): first-class transition visibility + low-noise autom...
by SmithLabsLLC · 2026-02-22
79.8%