#12191: fix: guard against undefined model.input in display and scan layers
commands
agents
size: S
trusted-contributor
experienced-contributor
Cluster:
Model Input and Streaming Fixes
## Summary
Fixes #12165
Models from custom providers (e.g. xAI/Grok, local Ollama) may not include the `input` property in their model definition, causing `TypeError: Cannot read properties of undefined (reading 'join')` or `TypeError: Cannot read properties of undefined (reading 'includes')` at runtime.
This PR adds defensive guards in the **display and scanning layers**:
- **`toModelRow()`** (`list.registry.ts`): Guards `model.input.join("+")` — prevents crash when running `openclaw models` list command
- **`ensureImageInput()`** (`model-scan.ts`): Guards `model.input.includes("image")` — prevents crash during OpenRouter model scanning
- **OpenRouter probe** (`model-scan.ts`): Guards inline `model.input.includes("image")` check
### Root cause
The pi-ai SDK's `Model` type declares `input: ("text" | "image")[]` as non-optional, but models constructed from custom provider configurations at runtime may omit this field entirely. The display and scan code paths trusted the type signature without runtime validation.
### Relationship to PR #9212
PR #9212 fixes the same class of bug in the **runtime model resolution path** (`pi-embedded-runner/model.ts`). This PR covers **different code paths** — the CLI model listing and OpenRouter scanning layers. Both fixes are complementary.
## Test plan
- [x] New test: `toModelRow()` with `model.input` undefined — crashes before fix, returns `"text"` after
- [x] New test: `toModelRow()` with empty `model.input` array — returns `"text"`
- [x] New test: `toModelRow()` with populated `model.input` — correctly joins as `"text+image"`
- [x] Existing `model-catalog.test.ts` tests pass (2/2)
- [x] Existing `model-scan.test.ts` tests pass (2/2)
- [x] `pnpm build` passes
- [x] `pnpm check` passes (lint + format)
- [x] All 3 new tests fail before fix, pass after (TDD)
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR adds runtime guards for cases where `model.input` is missing from custom-provider model definitions, preventing crashes in two CLI/model-management paths:
- `src/commands/models/list.registry.ts`: `toModelRow()` now treats a missing/non-array `model.input` as text-only and avoids calling `.join()` on `undefined`.
- `src/agents/model-scan.ts`: the OpenRouter scan/probe code now avoids calling `.includes()` on `undefined` and `ensureImageInput()` no longer assumes `model.input` is present.
It also adds a focused unit test for `toModelRow()` covering undefined/empty/multi-modal `input` cases.
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with minimal risk.
- Changes are narrowly scoped, add defensive nullish handling around a known runtime crash (`model.input` missing), and include targeted tests for the display path. The scan-layer guard is straightforward and preserves existing behavior for normal models.
- No files require special attention
<!-- greptile_other_comments_section -->
**Context used:**
- Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=fd949e91-5c3a-4ab5-90a1-cbe184fd6ce8))
- Context from `dashboard` - AGENTS.md ([source](https://app.greptile.com/review/custom-context?memory=0d0c8278-ef8e-4d6c-ab21-f5527e322f13))
<!-- /greptile_comment -->
Most Similar PRs
#9212: fix: ensure model.input is always an array for custom providers
by sparck75 · 2026-02-05
84.4%
#21963: fix(cli): models fallbacks add now includes primary model in allowlist
by ashiabbott · 2026-02-20
78.6%
#6673: fix: preserve allowAny flag in createModelSelectionState for custom...
by tenor0 · 2026-02-01
78.3%
#7741: fix: gracefully handle missing OpenRouter API key in models scan
by rohanjangala · 2026-02-03
77.8%
#14508: fix(models): allow forward-compat models in allowlist check
by jonisjongithub · 2026-02-12
77.6%
#16766: fix(model): apply provider baseUrl/headers override to registry-fou...
by dzianisv · 2026-02-15
77.6%
#9583: fix(models): allow models in agents.defaults.models even if not in ...
by hotzen100 · 2026-02-05
77.4%
#9905: fix: require provider prefix for models set without alias (#5790)
by petter-b · 2026-02-05
77.2%
#7570: fix: allow models from providers with auth profiles configured
by DonSqualo · 2026-02-03
77.2%
#9822: fix: allow local/custom model providers for sub-agent inference
by stammtobias91 · 2026-02-05
77.2%