← Back to PRs

#12191: fix: guard against undefined model.input in display and scan layers

by mcaxtr open 2026-02-09 00:06 View on GitHub →
commands agents size: S trusted-contributor experienced-contributor
## 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