{"record":{"id":"500f7350a2e22719","repo":"jdx/mise","slug":"github-relay-socket-forwarding-failed","errorCode":null,"errorMessage":"GitHub relay socket forwarding failed","messagePattern":"GitHub relay socket forwarding failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/remote.rs","lineNumber":722,"sourceCode":"    let relay = crate::github_relay::unix::Relay::start(scope, &session.host.name).await?;\n    let control = session\n        .control_path\n        .as_ref()\n        .ok_or_else(|| eyre!(\"relay requires an owned SSH control connection\"))?;\n    let status = tokio::process::Command::new(&session.ssh)\n        .kill_on_drop(true)\n        .arg(\"-S\")\n        .arg(control)\n        .args([\"-O\", \"forward\", \"-o\", \"ExitOnForwardFailure=yes\", \"-R\"])\n        .arg(format!(\n            \"{staging}/github.sock:{}\",\n            relay.socket().display()\n        ))\n        .arg(session.host.destination())\n        .status()\n        .await?;\n    if !status.success() {\n        bail!(\"GitHub relay socket forwarding failed\");\n    }\n    Ok(relay)\n}\n\n#[cfg(unix)]\npub(crate) async fn ssh(\n    host: &RemoteHost,\n    scope: crate::github_relay::Scope,\n    command: &[String],\n) -> Result<()> {\n    crate::ui::ctrlc::exit_on_ctrl_c(false);\n    let directory = tempfile::Builder::new()\n        .prefix(\"mise-ssh-\")\n        .tempdir_in(\"/tmp\")?;\n    let session = SshSession {\n        ssh: crate::file::which_spawnable(\"ssh\").ok_or_else(|| eyre!(\"ssh not found\"))?,\n        host,\n        relay: true,","sourceCodeStart":704,"sourceCodeEnd":740,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/remote.rs#L704-L740","documentation":"mise's GitHub relay lets a remote host borrow local GitHub credentials through a Unix socket forwarded over SSH (`ssh -O forward -R remote.sock:local.sock`). This error means the ssh multiplexed forward command exited non-zero, so the remote side has no socket to send GitHub requests through. mise throws it when the forwarding setup fails before the remote command starts.","triggerScenarios":"Calling `start_relay` from `run_staged` or `ssh` (Unix only, relay enabled); `ssh -S control -O forward -R staging/github.sock:local-relay.sock host` returns a non-zero status, e.g. with ExitOnForwardFailure=yes.","commonSituations":"The SSH server on the host disables TCP/streamlocal forwarding (AllowStreamLocalForwarding no); the remote staging socket path already exists or is not writable; the multiplexed control socket died between connection and forward request; the local relay socket path exceeds the 108-char Unix socket limit.","solutions":["Re-run the command; transient multiplexed-control failures often clear on a fresh connection","Check the host's sshd_config for AllowStreamLocalForwarding/AllowTcpForwarding restrictions and enable forwarding","Use a shorter staging directory path so the forwarded socket path fits the Unix socket length limit","Run with --no-relay style opt-out and provide GitHub credentials directly on the remote host instead","Delete a stale staging/github.sock on the remote before retrying"],"exampleFix":"# before: sshd_config on host blocks forwarding\nAllowTcpForwarding no\n# after\nAllowTcpForwarding yes\nAllowStreamLocalForwarding yes","handlingStrategy":"retry","validationCode":"# preflight: confirm forwarding is permitted\nssh -o ExitOnForwardFailure=yes -o ControlMaster=no host true && ssh -G host | grep -Ei 'forwarding'","typeGuard":null,"tryCatchPattern":"match start_relay(&session, staging, scope).await {\n    Ok(relay) => relay,\n    Err(e) if e.to_string().contains(\"relay socket forwarding failed\") => {\n        // retry once with a fresh connection, else fall back to remote credentials\n        tokio::time::sleep(Duration::from_secs(2)).await;\n        start_relay(&session, staging, scope).await?\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Enable AllowStreamLocalForwarding/AllowTcpForwarding in remote sshd_config","Keep staging paths short so forwarded socket names fit Unix socket limits","Clean stale sockets in the staging directory before reconnecting","Configure remote GitHub credentials as a fallback when relay is unavailable"],"tags":["ssh","relay","socket","network"],"backgroundTag":"connection-refused","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}