Bug type
Behavior bug (incorrect output/state without crash)
Beta release blocker
No
Summary
On macOS 15, when OpenClaw Gateway runs as a custom LaunchDaemon under a service user whose shell is /usr/bin/false, exec returns exitCode=1 after 3-10ms and does not execute the target command.
Steps to reproduce
- Run OpenClaw Gateway as a custom macOS LaunchDaemon under a dedicated service user.
- Use a service user whose login shell is
/usr/bin/false.
- Do not set
SHELL explicitly in the LaunchDaemon EnvironmentVariables.
- Run
exec against a trivial script such as:
- Observe that OpenClaw returns
exitCode=1 in a few milliseconds and the script body is never reached.
Expected behavior
In the same deployment, after explicitly setting SHELL=/bin/sh in the LaunchDaemon environment, the same minimal script returns exitCode=42 and real commands execute successfully.
Actual behavior
OpenClaw returns a completed exec result with exitCode=1, durationMs=3-10ms, and empty output. The target script is never invoked. After explicitly setting SHELL=/bin/sh in the LaunchDaemon plist, the same test script returns exitCode=42 and real commands execute successfully.
OpenClaw version
2026.4.16
Operating system
macOS 15 / Darwin 25.2.0
Install method
npm global
Model
ollama/qwen2.5:7b
Provider / routing chain
OpenClaw Gateway -> local Ollama (qwen2.5:7b)
Additional provider/model setup details
The provider/model setup did not affect reproduction. The failure reproduced with a minimal exec target script and also after temporarily setting tools.exec.security: "full" and tools.exec.ask: "off" to bypass allowlist behavior.
Logs, screenshots, and evidence
Observed tool result:
{
"status": "completed",
"exitCode": 1,
"durationMs": 4,
"aggregated": "\n\n(Command exited with code 1)"
}
Observed minimal repro script:
#!/bin/sh
exit 42
Observed verification after workaround:
- With `SHELL=/bin/sh` set in the LaunchDaemon environment, the minimal script returned `exitCode=42`, `durationMs=104`
- A real command returned `exitCode=0`, `durationMs=5410`, with valid JSON output
Additional direct evidence:
- `sudo -u _openclaw node -e 'console.log(process.env.SHELL)'` returned `/usr/bin/false`
- The target script did not execute before the workaround; debug logging placed at the first line of the script never ran
Impact and severity
Affected: custom headless macOS LaunchDaemon deployments using a dedicated service user with a non-login shell such as /usr/bin/false
Severity: High for affected setups because exec does not run at all
Frequency: 100% in observed attempts
Consequence: scheduled and interactive exec-based workflows fail while appearing to be normal completed command exits
Additional information
In the affected runtime, process.env.SHELL was /usr/bin/false. After explicitly setting SHELL=/bin/sh in the LaunchDaemon environment, the same repro passed immediately.
This was also isolated from allowlist behavior by temporarily setting tools.exec.security: "full" and tools.exec.ask: "off"; the failure still reproduced before the SHELL workaround.
Bug type
Behavior bug (incorrect output/state without crash)
Beta release blocker
No
Summary
On macOS 15, when OpenClaw Gateway runs as a custom LaunchDaemon under a service user whose shell is
/usr/bin/false,execreturnsexitCode=1after 3-10ms and does not execute the target command.Steps to reproduce
/usr/bin/false.SHELLexplicitly in the LaunchDaemonEnvironmentVariables.execagainst a trivial script such as:exitCode=1in a few milliseconds and the script body is never reached.Expected behavior
In the same deployment, after explicitly setting
SHELL=/bin/shin the LaunchDaemon environment, the same minimal script returnsexitCode=42and real commands execute successfully.Actual behavior
OpenClaw returns a completed exec result with
exitCode=1,durationMs=3-10ms, and empty output. The target script is never invoked. After explicitly settingSHELL=/bin/shin the LaunchDaemon plist, the same test script returnsexitCode=42and real commands execute successfully.OpenClaw version
2026.4.16
Operating system
macOS 15 / Darwin 25.2.0
Install method
npm global
Model
ollama/qwen2.5:7b
Provider / routing chain
OpenClaw Gateway -> local Ollama (qwen2.5:7b)
Additional provider/model setup details
The provider/model setup did not affect reproduction. The failure reproduced with a minimal
exectarget script and also after temporarily settingtools.exec.security: "full"andtools.exec.ask: "off"to bypass allowlist behavior.Logs, screenshots, and evidence
Observed tool result: { "status": "completed", "exitCode": 1, "durationMs": 4, "aggregated": "\n\n(Command exited with code 1)" } Observed minimal repro script: #!/bin/sh exit 42 Observed verification after workaround: - With `SHELL=/bin/sh` set in the LaunchDaemon environment, the minimal script returned `exitCode=42`, `durationMs=104` - A real command returned `exitCode=0`, `durationMs=5410`, with valid JSON output Additional direct evidence: - `sudo -u _openclaw node -e 'console.log(process.env.SHELL)'` returned `/usr/bin/false` - The target script did not execute before the workaround; debug logging placed at the first line of the script never ranImpact and severity
Affected: custom headless macOS LaunchDaemon deployments using a dedicated service user with a non-login shell such as
/usr/bin/falseSeverity: High for affected setups because
execdoes not run at allFrequency: 100% in observed attempts
Consequence: scheduled and interactive exec-based workflows fail while appearing to be normal completed command exits
Additional information
In the affected runtime,
process.env.SHELLwas/usr/bin/false. After explicitly settingSHELL=/bin/shin the LaunchDaemon environment, the same repro passed immediately.This was also isolated from allowlist behavior by temporarily setting
tools.exec.security: "full"andtools.exec.ask: "off"; the failure still reproduced before theSHELLworkaround.