davila7/claude-code-templates · error · anyhow::Error
failed to launch Node CLI
Error message
failed to launch Node CLI: {e}. Is Node.js installed? What it means
Rust CLI error when spawning the Node CLI subprocess fails: Command::status() returns Err, meaning the node executable could not be launched at all (not that the CLI errored). The message suggests Node.js is missing or not on PATH.
Solutions
- Verify node is installed and on PATH: `node --version` from the same environment
- Use an absolute node path or fix PATH (nvm use, or add node to the invoking environment's PATH)
- Reinstall Node.js (>= required version) if the binary is broken
- On Linux/macOS check execute permissions and ulimit on processes
Example fix
# before export PATH=/usr/local/bin:/usr/bin:/bin # node installed via nvm, not found # after export PATH="$HOME/.nvm/versions/node/v22.11.0/bin:$PATH" cli-rust --agent frontend-developer
Defensive patterns
Strategy: validation
Validate before calling
use std::process::Command;
fn node_available() -> bool {
Command::new("node").arg("--version").output().is_ok()
}
// call before delegate_to_node; fall back to npx or a bundled binary if false Try / catch
match cmd.status() {
Ok(status) => Ok(status.code().unwrap_or(1)),
Err(e) if e.kind() == std::io::ErrorKind::NotFound =>
suggest_install_node(),
Err(e) => Err(anyhow!("failed to launch Node CLI: {e}")),
} Prevention
- Check `node --version` during install of the Rust wrapper
- Resolve node via `which node` and pass an absolute path
- For GUI/CI launches, set PATH explicitly to include the Node bin directory
When it happens
Trigger: Running the Rust wrapper (e.g. `cli-rust --agent x`) where `node` is not found (ENOENT), not executable (EACCES), or process limits prevent spawning.
Common situations: Node not installed or removed; PATH differs when invoked from a GUI/launcher/systemd vs a shell; nvm-managed node not on PATH in non-login shells; Windows without node.exe in PATH.
Related errors
AI-assisted analysis of davila7/claude-code-templates@a0851ed10c (2026-08-28).
Data as JSON: /api/errors/080226d4d91988f4.
Report an issue: GitHub.
Appendix: source
Thrown at cli-rust/src/commands/delegate.rs:19
//! Delegation to the existing Node.js CLI for features not yet ported natively
//! (dashboards, sandbox, global agents, stats, health-check, interactive setup).
//!
//! Resolution order for the Node entry point:
//! 1. `CCT_NODE_BIN` env var — path to `create-claude-config.js` (run with
//! `node`) or an executable to invoke directly. Used for local testing.
//! 2. Fallback: `npx -y claude-code-templates@latest <args>`.
//!
//! The original process args (everything after the binary name) are forwarded
//! verbatim with inherited stdio, so the delegated command behaves identically.
use anyhow::{anyhow, Result};
use std::process::Command;
pub fn delegate_to_node(forwarded_args: &[String]) -> Result<i32> {
let mut command = build_command(forwarded_args)?;
let status = command
.status()
.map_err(|e| anyhow!("failed to launch Node CLI: {e}. Is Node.js installed?"))?;
// Preserve the child's termination semantics: a normal exit code, or for a
// signal-killed child on Unix, the shell convention 128 + signal.
let code = status.code().unwrap_or_else(|| {
#[cfg(unix)]
{
use std::os::unix::process::ExitStatusExt;
status.signal().map(|s| 128 + s).unwrap_or(1)
}
#[cfg(not(unix))]
{
1
}
});
Ok(code)
}
fn build_command(forwarded_args: &[String]) -> Result<Command> {
if let Ok(node_bin) = std::env::var("CCT_NODE_BIN") {View on GitHub (pinned to a0851ed10c)