{"record":{"id":"add3dcf7933e495b","repo":"zed-industries/zed","slug":"ssh-connection-canceled","errorCode":null,"errorMessage":"SSH connection canceled","messagePattern":"SSH connection canceled","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/remote/src/transport/ssh.rs","lineNumber":687,"sourceCode":"            delegate.set_status(Some(\"Connecting\"), cx);\n\n            // Start the master SSH process, which does not do anything except\n            // for establish the connection and keep it open, allowing other ssh\n            // commands to reuse it via a control socket.\n            let socket_path = temp_dir.path().join(\"ssh.sock\");\n            let mut master_process = MasterProcess::new(\n                askpass.script_path().as_ref(),\n                connection_options.additional_args(),\n                &socket_path,\n                &destination,\n            )?;\n\n            let result = select_biased! {\n                result = askpass.run(Some(SSH_CONNECTION_PROMPT_TIMEOUT)).fuse() => {\n                    match result {\n                        AskPassResult::CancelledByUser => {\n                            master_process.as_mut().kill().ok();\n                            anyhow::bail!(\"SSH connection canceled\")\n                        }\n                        AskPassResult::Timedout => {\n                            anyhow::bail!(\"connecting to host timed out\")\n                        }\n                    }\n                }\n                _ = master_process.wait_connected().fuse() => {\n                    anyhow::Ok(())\n                }\n            };\n\n            if let Err(e) = result {\n                return Err(e.context(\"Failed to connect to host\"));\n            }\n\n            if master_process.as_mut().try_status()?.is_some() {\n                let mut output = Vec::new();\n                let mut stderr = master_process.as_mut().stderr.take().unwrap();","sourceCodeStart":669,"sourceCodeEnd":705,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/remote/src/transport/ssh.rs#L669-L705","documentation":"During SSH connection establishment Zed races the askpass credential prompt against the master connection; if the user dismisses the prompt (AskPassResult::CancelledByUser), the master process is killed and this error aborts the connect. It is deliberate, user-driven cancellation rather than a malfunction.","triggerScenarios":"Cancelling or dismissing the password/passphrase prompt shown while SshSocket is still connecting, causing select_biased! to resolve through the askpass branch, kill the master, and bail.","commonSituations":"Users backing out of a password dialog to fix a mistyped host or pick another key; prompts appearing unexpectedly so users dismiss them; headless test harnesses auto-dismissing dialogs.","solutions":["Retry the connection and complete the credential prompt","Configure non-interactive auth so the prompt never appears: ssh-agent with the key loaded, or an empty-passphrase key","For automation, supply credentials via SSH_ASKPASS helpers or key-based auth instead of interactive prompts"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match connect(&opts, cx).await {\n    Err(e) if e.to_string().contains(\"SSH connection canceled\") => {\n        // benign: user dismissed the prompt; do not retry, return to idle state\n        Ok(None)\n    }\n    other => other.map(Some),\n}","preventionTips":["Use ssh-agent or empty-passphrase keys to remove interactive prompts","Treat cancellation as a dead-end path, not an error to retry automatically","Automate with SSH_ASKPASS helpers instead of UI prompts"],"tags":["ssh","askpass","user-cancellation"],"backgroundTag":"ssh-auth-cancelled","analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}