openclaw - ✅(Solved) Fix [Bug]: `infer model run --local --prompt ""` reaches the provider; `--gateway` correctly rejects it (Claude shows "No text output returned"; DeepSeek silently bills) [2 pull requests, 4 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#73185Fetched 2026-04-29 06:22:27
View on GitHub
Comments
4
Participants
3
Timeline
17
Reactions
0
Author
Timeline (top)
cross-referenced ×5commented ×4labeled ×2mentioned ×2

pnpm openclaw infer model run --model <id> --prompt "" (and " ", $'\n') sends the empty/whitespace user turn to the provider with no client-side validation. Symptom is provider-dependent: against the default anthropic/claude-opus-4-7, the call goes out and returns with no content, surfacing as a misleading Error: No text output returned for provider "anthropic" model "claude-opus-4-7" (exit 1) — the user is told there's no output instead of told their prompt was empty. Against deepseek/deepseek-v4-flash, the same input is silently accepted, the model generates ~3.5 KB of unrelated content, and the user is billed (exit 0). Compare: omitting --prompt entirely is correctly rejected by Commander before any provider call. The presence check exists; the content check is missing.

Error Message

=== Verified matrix (single shell session, OpenClaw 2026.4.26 / 53b7e20, Node 22.22.2) ===

TRANSPORT PROVIDER PROMPT EXIT SYMPTOM local anthropic/claude-opus-4-7 "" 1 Error: No text output returned for provider "anthropic" model "claude-opus-4-7" local anthropic/claude-opus-4-7 " " 1 Same local deepseek/deepseek-v4-flash "" 0 ok=true, output_chars=376 (billed) local deepseek/deepseek-v4-flash " " 0 ok=true, output_chars=~300 (billed) gateway anthropic/claude-opus-4-7 "" 1 GatewayClientRequestError: invalid agent params: at /message: must NOT have fewer than 1 characters gateway anthropic/claude-opus-4-7 " " 1 GatewayClientRequestError: Error: Message (--message) is required gateway deepseek/deepseek-v4-flash "" 1 Same gateway rejection gateway deepseek/deepseek-v4-flash " " 1 Same gateway rejection

=== Local + claude (the bug, default path) ===

$ pnpm openclaw infer model run --local --model anthropic/claude-opus-4-7 --prompt "" Error: No text output returned for provider "anthropic" model "claude-opus-4-7". ELIFECYCLE Command failed with exit code 1.

$ pnpm openclaw infer model run --local --model anthropic/claude-opus-4-7 --prompt " " Error: No text output returned for provider "anthropic" model "claude-opus-4-7".

$ pnpm openclaw infer model run --local --model anthropic/claude-opus-4-7 --prompt $'\n' Error: No text output returned for provider "anthropic" model "claude-opus-4-7".

=== Local + deepseek --json (silent billing repro on permissive provider) ===

$ pnpm openclaw infer model run --local --model deepseek/deepseek-v4-flash --prompt "" --json { "ok": true, "capability": "model.run", "transport": "local", "provider": "deepseek", "model": "deepseek-v4-flash", "attempts": [], "outputs": [ { "text": "<376-char Chinese assistant turn>", "mediaUrl": null } ] }

=== Gateway + claude (in-tree counter-example: validation already exists) ===

$ pnpm openclaw infer model run --gateway --model anthropic/claude-opus-4-7 --prompt "" GatewayClientRequestError: invalid agent params: at /message: must NOT have fewer than 1 characters ELIFECYCLE Command failed with exit code 1.

$ pnpm openclaw infer model run --gateway --model anthropic/claude-opus-4-7 --prompt " " GatewayClientRequestError: Error: Message (--message) is required ELIFECYCLE Command failed with exit code 1.

=== Counter-example: missing --prompt is rejected by Commander on both transports ===

$ pnpm openclaw infer model run --model anthropic/claude-opus-4-7 error: required option '--prompt <text>' not specified ELIFECYCLE Command failed with exit code 1.

=== Sanity check: Claude works correctly with real prompts on both transports ===

$ pnpm openclaw infer model run --local --model anthropic/claude-opus-4-7 --prompt "Say hello in one short sentence." Hello, nice to meet you!

$ pnpm openclaw infer model run --gateway --model anthropic/claude-opus-4-7 --prompt "Say hello in one short sentence." Hello! Hope your night is going well.

Root Cause

  1. Fresh checkout of openclaw at v2026.4.26 (commit 53b7e20); pnpm install && pnpm build on Node 22.22.2.
  2. With the default model set to anthropic/claude-opus-4-7 and anthropic auth configured (Claude CLI OAuth in this run).
  3. Run pnpm openclaw infer model run --model anthropic/claude-opus-4-7 --prompt "".
  4. Observe Error: No text output returned for provider "anthropic" model "claude-opus-4-7" and exit 1 — but the request reached the provider; the error is downstream of dispatch.
  5. Repeat with --prompt " " and --prompt $'\n' — same misleading error, request still goes out.
  6. For comparison, omit --prompt entirely: pnpm openclaw infer model run --model anthropic/claude-opus-4-7 — Commander correctly errors with error: required option --prompt <text> not specified and exits 1 before any provider call.
  7. Optional secondary repro on a different provider to confirm root cause is in the CLI seam: configure deepseek and run pnpm openclaw infer model run --model deepseek/deepseek-v4-flash --prompt "" — completes with "ok": true, exit 0, and a ~3.5 KB unrelated assistant turn.

Fix Action

Fix / Workaround

  1. Fresh checkout of openclaw at v2026.4.26 (commit 53b7e20); pnpm install && pnpm build on Node 22.22.2.
  2. With the default model set to anthropic/claude-opus-4-7 and anthropic auth configured (Claude CLI OAuth in this run).
  3. Run pnpm openclaw infer model run --model anthropic/claude-opus-4-7 --prompt "".
  4. Observe Error: No text output returned for provider "anthropic" model "claude-opus-4-7" and exit 1 — but the request reached the provider; the error is downstream of dispatch.
  5. Repeat with --prompt " " and --prompt $'\n' — same misleading error, request still goes out.
  6. For comparison, omit --prompt entirely: pnpm openclaw infer model run --model anthropic/claude-opus-4-7 — Commander correctly errors with error: required option --prompt <text> not specified and exits 1 before any provider call.
  7. Optional secondary repro on a different provider to confirm root cause is in the CLI seam: configure deepseek and run pnpm openclaw infer model run --model deepseek/deepseek-v4-flash --prompt "" — completes with "ok": true, exit 0, and a ~3.5 KB unrelated assistant turn.

--prompt should be validated as a non-empty, non-whitespace-only string before any provider request is dispatched. On empty or whitespace-only input the CLI should print a clear error such as error: --prompt cannot be empty or whitespace-only and exit non-zero with no provider call.

  • Likely fix locus: the argument handler for infer model run (commander definition for the subcommand under src/cli/cli-infer/ or wherever the parser lives in this build). Add a validator on the --prompt value that rejects empty strings and /^\s*$/-only strings before dispatching to the capability runner. The shared CLI helpers under src/cli/program/ already validate other required-option presence; this is the same pattern but on content.

PR fix notes

PR #73213: fix(cli): reject empty/whitespace-only --prompt for infer model run

Description (problem / solution / changelog)

Fixes #73185

Summary

openclaw infer model run --local --prompt "" (and " ", "\n") sent the empty user turn straight to the provider with no client-side validation. Anthropic surfaced a misleading Error: No text output returned after a real round-trip; DeepSeek silently billed for ~3.5 KB of unrelated content. The --gateway transport already enforces a minLength: 1 JSON-schema check on /message; this PR adds the equivalent guard on the --local path. In the model run action of src/cli/capability-cli.ts, trim the resolved --prompt and throw --prompt cannot be empty or whitespace-only before dispatch. No production transport / provider code touched.

Test plan

  • pnpm test src/cli/capability-cli.test.ts
  • pnpm check:changed
  • End-to-end on the real CLI for all 3 repro inputs from the issue + the existing in-tree baseline (missing --prompt).

Evidence

Unit test:

 Test Files  1 passed (1)
      Tests  39 passed (39)

(38 existing + 1 new test covering "", " ", "\n", mixed whitespace; the new test asserts prepareSimpleCompletionModelForAgent, completeWithPreparedSimpleCompletionModel, and callGateway are never invoked.)

pnpm check:changedEXIT=0.

End-to-end on the real CLI (OpenClaw 2026.4.26, Node 22.14, Linux):

$ pnpm openclaw infer model run --prompt ""
Error: --prompt cannot be empty or whitespace-only
 ELIFECYCLE  Command failed with exit code 1.

$ pnpm openclaw infer model run --prompt "   "
Error: --prompt cannot be empty or whitespace-only
 ELIFECYCLE  Command failed with exit code 1.

$ pnpm openclaw infer model run --prompt $'\n'
Error: --prompt cannot be empty or whitespace-only
 ELIFECYCLE  Command failed with exit code 1.

# Baseline (already worked before this PR; the in-tree reference Commander check):
$ pnpm openclaw infer model run
error: required option '--prompt <text>' not specified
 ELIFECYCLE  Command failed with exit code 1.

In all three blank-input cases the process exited before any provider dispatch — no auth prompt, no network round-trip, no billing.

Risks

None. The new branch fires only on inputs that previously produced misleading errors or billed degenerate completions, and only on the model run subcommand. Other --prompt callers (image describe, etc. at lines 1593/1632/1734/1981) are out of scope and unchanged. Error message matches the reporter's suggested wording for consistency with the gateway-side schema rejection.

Changed files

  • src/cli/capability-cli.test.ts (modified, +25/-0)
  • src/cli/capability-cli.ts (modified, +11/-1)

PR #73258: fix(cli): reject empty or whitespace-only --prompt in model run

Description (problem / solution / changelog)

Summary

openclaw infer model run --local --prompt "" sends empty/whitespace input to the provider with no client-side validation. This causes:

  • Claude: misleading "No text output returned" error after a real provider round-trip
  • DeepSeek (and similar providers): silently billed ~3.5 KB unrelated response

Adding a trim().length === 0 guard before dispatching to the provider, so empty strings, whitespace-only, and newline-only prompts fail fast with a clear error message and zero provider calls.

Root Cause

--prompt uses Commander's requiredOption() which only checks argument presence, not content. The --gateway transport path already rejects empty input via gateway-side JSON-schema validation (must NOT have fewer than 1 characters); the --local path had no equivalent guard.

Changes

FileChange
src/cli/capability-cli.ts+4 lines: prompt.trim() guard in model run action
src/cli/capability-cli.test.ts+23 lines: regression test covering "", " ", "\n"

Testing

  • 39/39 tests pass in src/cli/capability-cli.test.ts
  • Typecheck clean (tsgo:core + tsgo:core:test)
  • Formatting clean (oxfmt)
  • Provider seams verified never called for empty prompts

Expected Behavior After Fix

$ openclaw capability model run --prompt ""
error: --prompt cannot be empty or whitespace-only
(exit 1, no provider call)

Closes #73185

Changed files

  • src/cli/capability-cli.test.ts (modified, +23/-0)
  • src/cli/capability-cli.ts (modified, +5/-1)

Code Example

=== Verified matrix (single shell session, OpenClaw 2026.4.26 / 53b7e20, Node 22.22.2) ===

TRANSPORT  PROVIDER                       PROMPT  EXIT  SYMPTOM
local      anthropic/claude-opus-4-7      ""      1     Error: No text output returned for provider "anthropic" model "claude-opus-4-7"
local      anthropic/claude-opus-4-7      "   "   1     Same
local      deepseek/deepseek-v4-flash     ""      0     ok=true, output_chars=376 (billed)
local      deepseek/deepseek-v4-flash     "   "   0     ok=true, output_chars=~300 (billed)
gateway    anthropic/claude-opus-4-7      ""      1     GatewayClientRequestError: invalid agent params: at /message: must NOT have fewer than 1 characters
gateway    anthropic/claude-opus-4-7      "   "   1     GatewayClientRequestError: Error: Message (--message) is required
gateway    deepseek/deepseek-v4-flash     ""      1     Same gateway rejection
gateway    deepseek/deepseek-v4-flash     "   "   1     Same gateway rejection

=== Local + claude (the bug, default path) ===

$ pnpm openclaw infer model run --local --model anthropic/claude-opus-4-7 --prompt ""
Error: No text output returned for provider "anthropic" model "claude-opus-4-7".
 ELIFECYCLE  Command failed with exit code 1.

$ pnpm openclaw infer model run --local --model anthropic/claude-opus-4-7 --prompt "   "
Error: No text output returned for provider "anthropic" model "claude-opus-4-7".

$ pnpm openclaw infer model run --local --model anthropic/claude-opus-4-7 --prompt $'\n'
Error: No text output returned for provider "anthropic" model "claude-opus-4-7".

=== Local + deepseek --json (silent billing repro on permissive provider) ===

$ pnpm openclaw infer model run --local --model deepseek/deepseek-v4-flash --prompt "" --json
{
  "ok": true,
  "capability": "model.run",
  "transport": "local",
  "provider": "deepseek",
  "model": "deepseek-v4-flash",
  "attempts": [],
  "outputs": [
    { "text": "<376-char Chinese assistant turn>", "mediaUrl": null }
  ]
}

=== Gateway + claude (in-tree counter-example: validation already exists) ===

$ pnpm openclaw infer model run --gateway --model anthropic/claude-opus-4-7 --prompt ""
GatewayClientRequestError: invalid agent params: at /message: must NOT have fewer than 1 characters
 ELIFECYCLE  Command failed with exit code 1.

$ pnpm openclaw infer model run --gateway --model anthropic/claude-opus-4-7 --prompt "   "
GatewayClientRequestError: Error: Message (--message) is required
 ELIFECYCLE  Command failed with exit code 1.

=== Counter-example: missing --prompt is rejected by Commander on both transports ===

$ pnpm openclaw infer model run --model anthropic/claude-opus-4-7
error: required option '--prompt <text>' not specified
 ELIFECYCLE  Command failed with exit code 1.

=== Sanity check: Claude works correctly with real prompts on both transports ===

$ pnpm openclaw infer model run --local --model anthropic/claude-opus-4-7 --prompt "Say hello in one short sentence."
Hello, nice to meet you!

$ pnpm openclaw infer model run --gateway --model anthropic/claude-opus-4-7 --prompt "Say hello in one short sentence."
Hello! Hope your night is going well.
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

pnpm openclaw infer model run --model <id> --prompt "" (and " ", $'\n') sends the empty/whitespace user turn to the provider with no client-side validation. Symptom is provider-dependent: against the default anthropic/claude-opus-4-7, the call goes out and returns with no content, surfacing as a misleading Error: No text output returned for provider "anthropic" model "claude-opus-4-7" (exit 1) — the user is told there's no output instead of told their prompt was empty. Against deepseek/deepseek-v4-flash, the same input is silently accepted, the model generates ~3.5 KB of unrelated content, and the user is billed (exit 0). Compare: omitting --prompt entirely is correctly rejected by Commander before any provider call. The presence check exists; the content check is missing.

Steps to reproduce

  1. Fresh checkout of openclaw at v2026.4.26 (commit 53b7e20); pnpm install && pnpm build on Node 22.22.2.
  2. With the default model set to anthropic/claude-opus-4-7 and anthropic auth configured (Claude CLI OAuth in this run).
  3. Run pnpm openclaw infer model run --model anthropic/claude-opus-4-7 --prompt "".
  4. Observe Error: No text output returned for provider "anthropic" model "claude-opus-4-7" and exit 1 — but the request reached the provider; the error is downstream of dispatch.
  5. Repeat with --prompt " " and --prompt $'\n' — same misleading error, request still goes out.
  6. For comparison, omit --prompt entirely: pnpm openclaw infer model run --model anthropic/claude-opus-4-7 — Commander correctly errors with error: required option --prompt <text> not specified and exits 1 before any provider call.
  7. Optional secondary repro on a different provider to confirm root cause is in the CLI seam: configure deepseek and run pnpm openclaw infer model run --model deepseek/deepseek-v4-flash --prompt "" — completes with "ok": true, exit 0, and a ~3.5 KB unrelated assistant turn.

Expected behavior

--prompt should be validated as a non-empty, non-whitespace-only string before any provider request is dispatched. On empty or whitespace-only input the CLI should print a clear error such as error: --prompt cannot be empty or whitespace-only and exit non-zero with no provider call.

Concrete grounded reference from the same CLI/build: omitting --prompt entirely already fails fast and refuses to call the provider — infer model run --model anthropic/claude-opus-4-7 returns error: required option '--prompt <text>' not specified and exits 1. The presence check exists; only the content check is missing. Empty-string and whitespace-only inputs should follow the same fail-fast contract as the missing case, since neither carries any user intent.

Today, both default-path users (Claude → confusing "No text output returned" error after a real provider round-trip) and side-provider users (DeepSeek → silent billed completion) are funneled into the same upstream gap.

Actual behavior

$ pnpm openclaw infer model run --model anthropic/claude-opus-4-7 --prompt "" Error: No text output returned for provider "anthropic" model "claude-opus-4-7". ELIFECYCLE Command failed with exit code 1.

$ pnpm openclaw infer model run --model anthropic/claude-opus-4-7 --prompt " " Error: No text output returned for provider "anthropic" model "claude-opus-4-7". ELIFECYCLE Command failed with exit code 1.

$ pnpm openclaw infer model run --model anthropic/claude-opus-4-7 error: required option '--prompt <text>' not specified ELIFECYCLE Command failed with exit code 1.

$ pnpm openclaw infer model run --model deepseek/deepseek-v4-flash --prompt "" --json | jq '{ok, transport, provider, model, attempts, output_chars: (.outputs[0].text | length)}' { "ok": true, "transport": "local", "provider": "deepseek", "model": "deepseek-v4-flash", "attempts": [], "output_chars": 3528 }

OpenClaw version

2026.4.26

Operating system

Ubuntu 24.04

Install method

pnpm dev (source checkout from github.com/openclaw/openclaw; pnpm install && pnpm build; invoked via pnpm openclaw)

Model

anthropic/claude-opus-4-7 / deepseek/deepseek-v4-flash

Provider / routing chain

openclaw -> local transport -> anthropic openclaw -> local transport -> deepseek openclaw -> gateway (ws://127.0.0.1:18789) -> anthropic openclaw -> gateway (ws://127.0.0.1:18789) -> deepseek

Additional provider/model setup details

  • Default model: anthropic/claude-opus-4-7 (set via pnpm openclaw models set anthropic/claude-opus-4-7).
  • Anthropic auth: Claude CLI OAuth (detected by openclaw doctor; no manual login required for infer model run in this environment).
  • DeepSeek auth: registered via openclaw models auth login --provider deepseek (no --set-default); credential under ~/.openclaw/credentials/.
  • No per-agent overrides beyond the default main agent. No reverse proxy, no gateway proxy chain.

Logs, screenshots, and evidence

=== Verified matrix (single shell session, OpenClaw 2026.4.26 / 53b7e20, Node 22.22.2) ===

TRANSPORT  PROVIDER                       PROMPT  EXIT  SYMPTOM
local      anthropic/claude-opus-4-7      ""      1     Error: No text output returned for provider "anthropic" model "claude-opus-4-7"
local      anthropic/claude-opus-4-7      "   "   1     Same
local      deepseek/deepseek-v4-flash     ""      0     ok=true, output_chars=376 (billed)
local      deepseek/deepseek-v4-flash     "   "   0     ok=true, output_chars=~300 (billed)
gateway    anthropic/claude-opus-4-7      ""      1     GatewayClientRequestError: invalid agent params: at /message: must NOT have fewer than 1 characters
gateway    anthropic/claude-opus-4-7      "   "   1     GatewayClientRequestError: Error: Message (--message) is required
gateway    deepseek/deepseek-v4-flash     ""      1     Same gateway rejection
gateway    deepseek/deepseek-v4-flash     "   "   1     Same gateway rejection

=== Local + claude (the bug, default path) ===

$ pnpm openclaw infer model run --local --model anthropic/claude-opus-4-7 --prompt ""
Error: No text output returned for provider "anthropic" model "claude-opus-4-7".
 ELIFECYCLE  Command failed with exit code 1.

$ pnpm openclaw infer model run --local --model anthropic/claude-opus-4-7 --prompt "   "
Error: No text output returned for provider "anthropic" model "claude-opus-4-7".

$ pnpm openclaw infer model run --local --model anthropic/claude-opus-4-7 --prompt $'\n'
Error: No text output returned for provider "anthropic" model "claude-opus-4-7".

=== Local + deepseek --json (silent billing repro on permissive provider) ===

$ pnpm openclaw infer model run --local --model deepseek/deepseek-v4-flash --prompt "" --json
{
  "ok": true,
  "capability": "model.run",
  "transport": "local",
  "provider": "deepseek",
  "model": "deepseek-v4-flash",
  "attempts": [],
  "outputs": [
    { "text": "<376-char Chinese assistant turn>", "mediaUrl": null }
  ]
}

=== Gateway + claude (in-tree counter-example: validation already exists) ===

$ pnpm openclaw infer model run --gateway --model anthropic/claude-opus-4-7 --prompt ""
GatewayClientRequestError: invalid agent params: at /message: must NOT have fewer than 1 characters
 ELIFECYCLE  Command failed with exit code 1.

$ pnpm openclaw infer model run --gateway --model anthropic/claude-opus-4-7 --prompt "   "
GatewayClientRequestError: Error: Message (--message) is required
 ELIFECYCLE  Command failed with exit code 1.

=== Counter-example: missing --prompt is rejected by Commander on both transports ===

$ pnpm openclaw infer model run --model anthropic/claude-opus-4-7
error: required option '--prompt <text>' not specified
 ELIFECYCLE  Command failed with exit code 1.

=== Sanity check: Claude works correctly with real prompts on both transports ===

$ pnpm openclaw infer model run --local --model anthropic/claude-opus-4-7 --prompt "Say hello in one short sentence."
Hello, nice to meet you!

$ pnpm openclaw infer model run --gateway --model anthropic/claude-opus-4-7 --prompt "Say hello in one short sentence."
Hello! Hope your night is going well.

Impact and severity

Affected users/systems/channels:

  • Every operator using openclaw infer model run (alias openclaw capability model run) on the CLI. Linux directly observed (Ubuntu 24.04 / Node 22.22.2); the bug is in the CLI argument-handling seam upstream of provider/transport code, so behavior is expected on macOS/Windows installs but only Linux was directly reproduced.
  • Default-path users (Claude) see a confusing error that misattributes the cause to the provider rather than to their input.
  • Side-provider users (DeepSeek and any provider that auto-completes empty turns) get billed without a clear signal.

Severity:

  • For default Claude users: confusing UX. The error "No text output returned for provider 'anthropic' model 'claude-opus-4-7'" reads like a provider/model fault, sending users down the wrong debugging path.
  • For non-Claude users on a billing model: a real, repeatable cost component. Each accidental empty-prompt invocation is a billable round-trip producing an unrelated multi-KB response (~3.5 KB observed for one run on deepseek-v4-flash).
  • Easy to hit from shell scripts that interpolate an unset variable (--prompt "$VAR" with VAR=) or from accidentally-blank text in a heredoc.
  • Not a security issue and no data corruption observed.

Frequency:

  • Always, deterministic on --local. 100% reproduction across --prompt "", --prompt " ", and --prompt $'\n' for both providers tested. 0% reproduction on --gateway — that path correctly fails fast with the gateway's own JSON-schema validation. The bug is specific to --local transport; --gateway is the in-tree counter-example.

Consequence:

  • Misleading "No text output returned" errors blamed on provider/model when the real cause is empty user input.
  • On non-Claude providers: wasted provider tokens on degenerate inputs that the CLI never had to send.
  • Shell-script breakage: --prompt "$INPUT" with an empty $INPUT either silently bills (DeepSeek-shaped providers) or surfaces as a flapping "No text output returned" failure that triggers retries (Claude-shaped providers).
  • No grounded evidence of missed messages, failed onboarding, or data risk.

Additional information

  • Regression status: not classified as a Regression. Last-known-good not directly observed; no bisect performed.

  • Likely fix locus: the argument handler for infer model run (commander definition for the subcommand under src/cli/cli-infer/ or wherever the parser lives in this build). Add a validator on the --prompt value that rejects empty strings and /^\s*$/-only strings before dispatching to the capability runner. The shared CLI helpers under src/cli/program/ already validate other required-option presence; this is the same pattern but on content.

  • Suggested regression test: a unit test next to the infer model run action that asserts each of --prompt "", --prompt " ", and --prompt $'\n' on --local returns a non-zero exit and a "--prompt cannot be empty" error message, with the transport seam mocked to assert it is never called for empty/whitespace input. Pair with a parity test that confirms --local and --gateway produce equivalent rejection behavior for the same empty-content inputs (modulo error wording) — gateway-side validation already exists and is the in-tree reference.

  • Dedupe checked against the openclaw issue corpus on 2026-04-28: no existing open or closed issue matches. Closest text match is #34935 (closed) about safeguard compaction making an LLM call before checking for real messages — different code path (compaction, not CLI infer) but conceptually related (avoid billed calls on empty input). Could be cross-linked but is not a duplicate.

  • Not exercised in this repro: streaming-mode requests, per-agent overrides beyond main, batched/concurrent runs. The bug is upstream of provider selection so all providers reachable through infer model run are expected to be affected, with the exact symptom shape determined by each provider's empty-turn handling.

extent analysis

TL;DR

Add a content validator to the --prompt argument in the infer model run command to reject empty strings and whitespace-only strings before dispatching the request.

Guidance

  • Identify the commander definition for the infer model run subcommand and add a validator for the --prompt value.
  • The validator should check for empty strings and strings containing only whitespace characters (/^\s*$/).
  • If the input is invalid, return a clear error message (e.g., --prompt cannot be empty or whitespace-only) and exit with a non-zero status code.
  • Consider adding unit tests to verify the validator's behavior for different input scenarios.

Example

// Example validator function
function validatePrompt(prompt) {
  if (!prompt || /^\s*$/.test(prompt)) {
    throw new Error('--prompt cannot be empty or whitespace-only');
  }
}

// Example usage in the infer model run command
program
  .command('infer model run')
  .option('--prompt <text>', 'prompt text', validatePrompt)
  // ...

Notes

  • The fix should be applied to the infer model run command's argument handler, which is likely located in the src/cli/cli-infer/ directory.
  • The suggested regression test can help ensure the validator is working correctly and catch any future regressions.
  • The bug's impact is limited to the --local transport, while the --gateway transport already has validation in place.

Recommendation

Apply the workaround by adding a content validator to the --prompt argument in the infer model run command. This will prevent empty or whitespace-only strings from being dispatched to the provider, reducing the risk of misleading errors and unnecessary billing.

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…

FAQ

Expected behavior

--prompt should be validated as a non-empty, non-whitespace-only string before any provider request is dispatched. On empty or whitespace-only input the CLI should print a clear error such as error: --prompt cannot be empty or whitespace-only and exit non-zero with no provider call.

Concrete grounded reference from the same CLI/build: omitting --prompt entirely already fails fast and refuses to call the provider — infer model run --model anthropic/claude-opus-4-7 returns error: required option '--prompt <text>' not specified and exits 1. The presence check exists; only the content check is missing. Empty-string and whitespace-only inputs should follow the same fail-fast contract as the missing case, since neither carries any user intent.

Today, both default-path users (Claude → confusing "No text output returned" error after a real provider round-trip) and side-provider users (DeepSeek → silent billed completion) are funneled into the same upstream gap.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING