#23287: fix(node-host): improve ENOENT error when exec workspace dir is missing
size: XS
## Summary
- **Problem:** When `exec` runs on a node and the agent workspace directory does not exist, Node.js throws `spawn /bin/sh ENOENT`, misleadingly pointing at the shell binary rather than the real cause (missing `cwd`).
- **Why it matters:** Users spend hours debugging a non-existent shell problem when the actual fix is simply creating the workspace directory.
- **What changed:** In `src/node-host/invoke.ts`, the `child.on("error")` handler now checks whether a `cwd`-related ENOENT is the real cause and surfaces a clear diagnostic: `working directory does not exist: "<path>" — please create it or check your agent workspace config`.
- **What did NOT change:** The spawn call itself is unchanged. If the ENOENT is genuinely about the shell binary (not `cwd`), the original error message is preserved.
## Change Type (select all)
- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Docs
- [ ] Security hardening
- [ ] Chore/infra
## Scope (select all touched areas)
- [ ] Gateway / orchestration
- [x] Skills / tool execution
- [ ] Auth / tokens
- [ ] Memory / storage
- [ ] Integrations
- [ ] API / contracts
- [ ] UI / DX
- [ ] CI/CD / infra
## Linked Issue/PR
- Closes #22793
## User-visible / Behavior Changes
- When exec fails because the workspace directory is missing, the error now reads: \`working directory does not exist: "/path/to/workspace" — please create it or check your agent workspace config\` instead of the misleading \`spawn /bin/sh ENOENT\`.
## Security Impact (required)
- New permissions/capabilities? \`No\`
- Secrets/tokens handling changed? \`No\`
- New/changed network calls? \`No\`
- Command/tool execution surface changed? \`No\`
- Data access scope changed? \`No\`
## Repro + Verification
### Environment
- OS: macOS 15.3 (arm64), also applicable to Linux
- Runtime: Node v22+
- Integration/channel: Node exec (remote nodes)
### Steps
1. Register a new node/agent pair where the workspace dir does not exist
2. Trigger any exec command (e.g., \`whoami\`)
3. Observe the error message
### Expected
- Clear error: \`working directory does not exist: "<path>"\`
### Actual
- Before fix: \`spawn /bin/sh ENOENT\` (misleading — implies shell is missing)
- After fix: \`working directory does not exist: "<path>" — please create it or check your agent workspace config\`
## Evidence
Node.js \`child_process.spawn()\` throws ENOENT when the specified \`cwd\` does not exist, but the error message points at the binary (\`/bin/sh\`) rather than the directory. The fix intercepts ENOENT errors, checks if the \`cwd\` actually exists via \`fs.statSync()\`, and provides a targeted diagnostic if it doesn't.
```typescript
child.on("error", (err) => {
const nodeErr = err as NodeJS.ErrnoException;
if (nodeErr.code === "ENOENT" && cwd) {
try {
fs.statSync(cwd);
} catch {
finalize(undefined,
\`working directory does not exist: "\${cwd}" — please create it or check your agent workspace config\`);
return;
}
}
finalize(undefined, err.message);
});
```
## Human Verification (required)
- Verified scenarios: Reviewed Node.js spawn behavior — ENOENT is thrown for both missing binary and missing cwd; \`fs.statSync\` correctly distinguishes the two cases
- Edge cases checked: If cwd exists but binary is missing, the original error message is preserved; if cwd is \`undefined\`, the check is skipped entirely
- What I did **not** verify: Live remote node exec with missing workspace dir
## Compatibility / Migration
- Backward compatible? \`Yes\`
- Config/env changes? \`No\`
- Migration needed? \`No\`
## Failure Recovery (if this breaks)
- How to disable/revert: Revert the error handler change in \`invoke.ts\`
- Files/config to restore: \`src/node-host/invoke.ts\`
- Known bad symptoms: None — the check is purely diagnostic
## Risks and Mitigations
None — the fix only affects error message text; no behavior or control flow changes.
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Improved error diagnostics when exec fails due to missing workspace directory by detecting ENOENT errors and checking if the `cwd` exists via `fs.statSync`.
Key changes:
- Added error handler logic in `runCommand` to intercept ENOENT and provide clearer messaging when the working directory doesn't exist
- Error message now points to the actual missing directory instead of misleadingly referencing the shell binary
Issues found:
- The empty catch block around `fs.statSync` will incorrectly diagnose permission errors (EACCES) and other stat failures as "directory does not exist"
- Should use the existing `hasErrnoCode` utility from `src/infra/errors.ts` for consistent errno checking across the codebase
<h3>Confidence Score: 3/5</h3>
- Safe to merge with fixes for the stat error handling edge case
- The core improvement is valid and addresses a real UX pain point. However, the empty catch block around `fs.statSync` creates a logic error where permission denied and other filesystem errors will be misdiagnosed as "directory does not exist." This should be fixed before merging to ensure accurate error reporting.
- src/node-host/invoke.ts requires attention for the stat error handling logic
<sub>Last reviewed commit: 135ffa7</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#22812: fix(node-host): auto-create cwd before exec spawn to prevent mislea...
by aldoeliacim · 2026-02-21
87.9%
#22813: Return clear error when exec cwd is missing instead of spawn ENOENT
by Clawborn · 2026-02-21
86.3%
#9433: fix: pass raw command string to node exec instead of argv array
by dbottme · 2026-02-05
76.6%
#9200: Fix: Strip dangerous env vars from baseEnv in host execution
by vishaltandale00 · 2026-02-05
76.4%
#8038: fix(exec): use spawnWithFallback to handle EBADF on macOS
by FelixFoster · 2026-02-03
75.9%
#13577: fix(onboard): validate workspace directory before setup steps
by mcaxtr · 2026-02-10
75.6%
#9250: Fix: Add shell:true for Windows .cmd files to prevent spawn EINVAL ...
by vishaltandale00 · 2026-02-05
75.2%
#22917: fix: Use agent's configured workspace when spawned as subagent
by jriff · 2026-02-21
75.1%
#11961: fix: exec tool wraps shebang scripts in heredoc to use correct inte...
by scott-memco · 2026-02-08
73.5%
#23085: fix(workspace): respect OPENCLAW_STATE_DIR for workspace paths, fix...
by charojo · 2026-02-22
72.9%