#9433: fix: pass raw command string to node exec instead of argv array
agents
stale
Fixes #9235
## Summary
Commands executed via `host=node` (e.g., through DingTalk or webchat) were failing with `spawn /bin/sh ENOENT` errors, while the same commands worked correctly via CLI.
## Problem
When executing commands on remote nodes, the exec tool was passing a shell-wrapped argv array to the node's `system.run` command:
```javascript
params: {
command: argv, // e.g., ['/bin/sh', '-lc', 'ls'] - WRONG
rawCommand: params.command,
...
}
```
However, the node's `system.run` expects a command **string** and handles shell wrapping internally. When it received an array, `spawn()` failed because it expected a string for the executable.
## Solution
Pass the raw command string directly instead of the shell-wrapped argv array:
```javascript
params: {
command: params.command, // e.g., 'ls' - CORRECT
...
}
```
## Why CLI worked but Agent didn't
- **CLI path**: `openclaw nodes run` → Direct Node API call with correct parameter format
- **Agent path**: `exec tool` → `buildInvokeParams()` → Passed array instead of string → Node spawn failed
## Changes
- `src/agents/bash-tools.exec.ts`: Changed `command: argv` to `command: params.command` in `buildInvokeParams()`
- Removed unused `rawCommand` parameter since `command` now has the correct value
## Testing
After this fix, these commands should work via Agent channels (DingTalk, webchat, etc.):
- `hostname`
- `ls -la ~/Desktop`
- `pwd`
- `echo "test"`
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR updates the exec tool’s `host=node` path to send a raw command string to `system.run` instead of a shell-wrapped argv array, and removes the `rawCommand` field from the invoke params.
In the wider codebase, `system.run` requests are handled by the node host runner (`src/node-host/runner.ts`), which currently treats `params.command` as an argv array and uses `rawCommand` only as an optional display/allowlist evaluation override.
<h3>Confidence Score: 2/5</h3>
- This PR is not safe to merge as-is due to a likely runtime contract break in host=node execution.
- The change sends a string for `system.run` params.command, but the node host runner currently requires an argv array and will reject these requests, so the primary fix path appears incomplete within this PR.
- src/agents/bash-tools.exec.ts (and confirm compatibility with src/node-host/runner.ts)
<!-- 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
#9200: Fix: Strip dangerous env vars from baseEnv in host execution
by vishaltandale00 · 2026-02-05
82.0%
#21562: fix: exec host error message shows configuredHost instead of reques...
by TopangaLudwitt · 2026-02-20
77.5%
#23287: fix(node-host): improve ENOENT error when exec workspace dir is mis...
by SidQin-cyber · 2026-02-22
76.6%
#11961: fix: exec tool wraps shebang scripts in heredoc to use correct inte...
by scott-memco · 2026-02-08
76.1%
#22812: fix(node-host): auto-create cwd before exec spawn to prevent mislea...
by aldoeliacim · 2026-02-21
74.4%
#6064: fix(daemon): prefer bundled node from install-cli.sh over system node
by joyshmitz · 2026-02-01
74.4%
#21509: fix: show requestedHost instead of configuredHost in exec host erro...
by sleitor · 2026-02-20
74.0%
#21271: fix(commands): pass channel/capabilities/shell/os to runtime in com...
by evansantos · 2026-02-19
74.0%
#20014: fix(nodes): use formatExecCommand for approval request command text
by openperf · 2026-02-18
73.9%
#21280: fix(exec): reflect configured exec host in tool schema default (#11...
by Asm3r96 · 2026-02-19
73.7%