jdx/mise · error
GitHub relay socket forwarding failed
Error message
GitHub relay socket forwarding failed
What it means
start_relay launches an SSH process (with -R/remote-forward args built around relay.socket()) to forward a socket to GitHub for remote operations. If the ssh subprocess exits non-zero, mise bails with this error because the relay tunnel could not be established, and no GitHub traffic can flow over it.
Source
Thrown at src/system/remote.rs:720
let relay = crate::github_relay::unix::Relay::start(scope, &session.host.name).await?;
let control = session
.control_path
.as_ref()
.ok_or_else(|| eyre!("relay requires an owned SSH control connection"))?;
let status = tokio::process::Command::new(&session.ssh)
.kill_on_drop(true)
.arg("-S")
.arg(control)
.args(["-O", "forward", "-o", "ExitOnForwardFailure=yes", "-R"])
.arg(format!(
"{staging}/github.sock:{}",
relay.socket().display()
))
.arg(session.host.destination())
.status()
.await?;
if !status.success() {
bail!("GitHub relay socket forwarding failed");
}
Ok(relay)
}
#[cfg(unix)]
pub(crate) async fn ssh(
host: &RemoteHost,
scope: crate::github_relay::Scope,
command: &[String],
) -> Result<()> {
crate::ui::ctrlc::exit_on_ctrl_c(false);
let directory = tempfile::Builder::new()
.prefix("mise-ssh-")
.tempdir_in("/tmp")?;
let session = SshSession {
ssh: crate::file::which("ssh").ok_or_else(|| eyre!("ssh not found"))?,
host,
relay: true,View on GitHub (pinned to afd2eddd3a)
Solutions
- Run the same ssh command manually (host shown after relay.socket() in the error context) to see the real SSH error
- Verify SSH key/auth works: ssh -T <host destination>
- Check the remote sshd config allows TCP forwarding (AllowTcpForwarding yes)
- Confirm the host destination and network/VPN connectivity
- Inspect relay.socket() permissions on unix; the local socket must be accessible to ssh
Example fix
// before: opaque failure
if !status.success() {
bail!("GitHub relay socket forwarding failed");
}
// after: surface ssh stderr
if !status.success() {
bail!("GitHub relay socket forwarding failed (ssh exited {status}); run ssh with -vvv to diagnose");
} Defensive patterns
Strategy: retry
Validate before calling
const ok = await new Promise(res => { const p = spawn('ssh', ['-o','BatchMode=yes','-o','ConnectTimeout=5', host, 'true']); p.on('exit', c => res(c === 0)); }); Try / catch
try { await startRelay(); } catch (e) { if (String(e).includes('relay socket forwarding failed')) { await sshDiagnose(host); } throw e; } Prevention
- Smoke-test SSH auth (ssh -o BatchMode=yes host true) before relayed operations
- Keep sshd AllowTcpForwarding enabled on relay hosts
- Pin known-good SSH host keys and config aliases
When it happens
Trigger: The ssh command spawned by start_relay (invoked from run_staged or ssh) returns a non-zero exit status — e.g. bad SSH credentials/key, unreachable host, rejected port in the relay destination, or sshd refusing the forward.
Common situations: Developers running `mise run-staged` or remote SSH-backed workflows hit this when their ~/.ssh/config has an Alias that no longer resolves, the remote host changed its sshd MaxSessions/AllowTcpForwarding settings, or a VPN is down so the host destination is unreachable.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- remote host '{}' port must be greater than zero
- remote host '{}' identity file does not exist: {}
- remote host '{}' mise binary does not exist: {}
- invalid remote global configuration path
- failed to archive remote source with {status}
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/500f7350a2e22719.
Report an issue: GitHub.