BigPizzaV3/CodexPlusPlus · error · std::io::Error

Cannot run remote git over SSH

Error message

Cannot run remote git over SSH: {error}

What it means

spawn_remote_git builds an ssh command to run git remotely and calls command.output(). If the ssh process itself cannot be spawned or awaited (the OS fails to start it), the error is re-wrapped as "Cannot run remote git over SSH: {error}" preserving the original kind. This indicates an environment/spawn problem, not a remote git failure (non-zero exit is reported via status_success instead).

Solutions

  1. Verify ssh is installed and on PATH: run `ssh -V`
  2. Check the remote git command spec (destination, port, command) for malformed values
  3. Ensure the ssh binary has execute permission (chmod +x) and matches the platform
  4. Install openssh-client in the environment (e.g. apt-get install openssh-client in CI images)

Example fix

// before
let output = command.output().map_err(|error| {
    std::io::Error::new(error.kind(), format!("Cannot run remote git over SSH: {error}"))
})?;
// after
// validate ssh availability first
which::which("ssh").map_err(|_| std::io::Error::new(
    std::io::ErrorKind::NotFound, "ssh binary not found on PATH"))?;
let output = command.output().map_err(|error| {
    std::io::Error::new(error.kind(), format!("Cannot run remote git over SSH: {error}"))
})?;
Defensive patterns

Strategy: validation

Validate before calling

if (!process.env.PATH?.split(path.delimiter).some(d => fs.existsSync(path.join(d, 'ssh')))) {
  throw new Error('ssh not found on PATH');
}

Type guard

const sshAvailable = (): boolean => { try { require('child_process').execSync('ssh -V', {stdio:'ignore'}); return true; } catch { return false; } };

Try / catch

match remote_git(spec) {
    Err(e) if e.to_string().starts_with("Cannot run remote git over SSH") => {
        eprintln!("ssh spawn failed: {e}; check PATH and ssh install");
        Err(e)
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling remote_git or remote_shell when the ssh binary is missing from PATH, the command spec is malformed so the OS refuses exec, or permission/exec-format issues prevent spawning ssh.

Common situations: ssh not installed or not on PATH; ssh binary not executable; wrong port/destination values causing argument construction to fail; containerized/CI environments lacking openssh-client; Windows without an ssh in PATH.

Related errors


AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19). Data as JSON: /api/errors/567471ebf2d84b9b. Report an issue: GitHub.

Appendix: source

Thrown at crates/codex-plus-core/src/upstream_worktree/remote.rs:103

    RemoteGitCommand {
        destination: ssh_destination(target),
        port: target.port,
        command: remote_command,
    }
}

fn spawn_remote_git(command_spec: &RemoteGitCommand) -> Result<GitOutput, std::io::Error> {
    let mut command = Command::new("ssh");
    command.arg("-o").arg("BatchMode=yes");
    command.arg("-o").arg("ConnectTimeout=8");
    if let Some(port) = command_spec.port {
        command.arg("-p").arg(port.to_string());
    }
    command
        .arg(&command_spec.destination)
        .arg(&command_spec.command);
    let output = command.output().map_err(|error| {
        std::io::Error::new(
            error.kind(),
            format!("Cannot run remote git over SSH: {error}"),
        )
    })?;
    Ok(GitOutput {
        status_success: output.status.success(),
        stdout: String::from_utf8_lossy(&output.stdout).trim().to_string(),
        stderr: String::from_utf8_lossy(&output.stderr).trim().to_string(),
    })
}

fn remote_git(project: &UpstreamRemoteProject, args: &[&str]) -> UpstreamWorktreeResult<GitOutput> {
    let target = resolve_ssh_target_for_host_id(&project.host_id, None).map_err(|error| {
        UpstreamWorktreeError::new(UpstreamWorktreeCode::GitMissing, error.to_string())
    })?;
    let command_spec = remote_git_command(project, &target, args);
    let output = spawn_remote_git(&command_spec).map_err(|error| {
        UpstreamWorktreeError::new(UpstreamWorktreeCode::GitMissing, error.to_string())

View on GitHub (pinned to b1ed92e5e4)