Summary
When an exec command produces no stdout (e.g. grep with no matches, mkdir, cp, silent git commands), the exec runtime constructs a tool_result content block with text: "". Anthropic's API rejects empty text content blocks, causing the session to error out — typically after bulk operations that include several silent commands.
Root Cause
In bash-tools.exec-runtime:
const tailText = session.tail || session.aggregated;
const warningText = opts.warnings.length ? `${opts.warnings.join("\n")}\n\n` : "";
opts.onUpdate({
content: [{
type: "text",
text: warningText + (tailText || "") // ← empty string when no output
}],
...
});
When both warningText and tailText are empty, text becomes "".
Fix
text: warningText + (tailText || "(no output)")
Single-character change. Falls back to a non-empty placeholder only when the command produced no output, keeping existing behaviour for all non-empty cases.
Reproduction
# Any silent command with no stdout
mkdir /tmp/test-dir
grep 'nonexistent' /dev/null
Run several in sequence in a session — subsequent API call fails with content block validation error.
Environment
- OpenClaw v2026.4.11
- Provider: Anthropic (amazon-bedrock)
- Surface: telegram direct
Summary
When an exec command produces no stdout (e.g.
grepwith no matches,mkdir,cp, silentgitcommands), the exec runtime constructs atool_resultcontent block withtext: "". Anthropic's API rejects empty text content blocks, causing the session to error out — typically after bulk operations that include several silent commands.Root Cause
In
bash-tools.exec-runtime:When both
warningTextandtailTextare empty,textbecomes"".Fix
Single-character change. Falls back to a non-empty placeholder only when the command produced no output, keeping existing behaviour for all non-empty cases.
Reproduction
Run several in sequence in a session — subsequent API call fails with content block validation error.
Environment