aaif-goose/goose · error

failed to exec TUI ({descriptor}): {err}

Error message

failed to exec TUI ({descriptor}): {err}

What it means

On unix the TUI launcher uses Command::exec, which replaces the goose process with node/npx; exec only RETURNS when it fails. So this message always carries a raw OS error: usually NotFound (node or npx missing from PATH), NoSuchFile (local TUI script path wrong), or PermissionDenied. The descriptor names exactly what was exec'd (node <script> or npx --package <spec>).

Source

Thrown at crates/goose-cli/src/commands/tui.rs:83

pub fn handle_tui(args: Vec<String>) -> Result<()> {
    let source = resolve_source();

    let goose_binary = std::env::current_exe()
        .context("could not determine current goose executable to expose as GOOSE_BINARY")?;

    let mut cmd = build_command(&source, &args)?;
    cmd.env("GOOSE_BINARY", &goose_binary);

    let descriptor = match &source {
        TuiSource::LocalScript(p) => format!("node {}", p.display()),
        TuiSource::Npx(spec) => format!("npx --package {} -- {}", spec, NPM_BIN_NAME),
    };

    #[cfg(unix)]
    {
        use std::os::unix::process::CommandExt;
        let err = cmd.exec();
        Err(anyhow!("failed to exec TUI ({descriptor}): {err}"))
    }

    #[cfg(not(unix))]
    {
        let status = cmd
            .status()
            .with_context(|| format!("failed to run `{descriptor}`"))?;
        if !status.success() {
            std::process::exit(status.code().unwrap_or(1));
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::fs;

View on GitHub (pinned to 3810898a74)

Solutions

  1. Run the descriptor command yourself (e.g. `node --version`, `npx --version`) to reproduce the exact OS error
  2. Install Node.js or fix PATH so node/npx resolve in goose's environment
  3. For a local script source, verify the path exists and has execute permission
  4. If behind a proxy, ensure npm/npx can fetch the TUI package

Example fix

# before
goose tui        # failed to exec TUI (npx --package @block/goose-tui -- goose-tui): No such file or directory
# after
which node npx    # both must resolve
export PATH="$HOME/.nvm/versions/node/v22/bin:$PATH"
goose tui
Defensive patterns

Strategy: validation

Validate before calling

let node_ok = std::process::Command::new("node")
    .arg("--version")
    .output()
    .map(|o| o.status.success())
    .unwrap_or(false);
if !node_ok {
    anyhow::bail!("node not available on PATH; install Node.js before launching the TUI");
}

Type guard

fn node_available() -> bool {
    std::process::Command::new("node")
        .arg("--version")
        .output()
        .map(|o| o.status.success())
        .unwrap_or(false)
}

Try / catch

match run_tui(source, args).await {
    Err(e) if e.to_string().contains("failed to exec TUI") => {
        if e.to_string().contains("NotFound") || e.to_string().contains("No such file") {
            // node/npx missing from PATH: surface an install hint
        }
        Err(e)
    }
    other => other,
}

Prevention

When it happens

Trigger: `goose tui` / TUI launch with Node.js not installed or not on PATH for the goose process; --tui-source pointing at a moved/deleted script; script lacking execute permission; npx wrapper unavailable.

Common situations: Minimal containers/servers without node; PATH differing between login shell and the environment goose runs in (launchers, service managers); stale local TUI path after moving the repo.

Related errors


AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16). Data as JSON: /api/errors/710bcdb4da133e4a. Report an issue: GitHub.