{"record":{"id":"358c891c44633a33","repo":"zed-industries/zed","slug":"failed-to-upload-file-via-stfp-scp","errorCode":null,"errorMessage":"failed to upload file via STFP/SCP {} -> {}: {}","messagePattern":"failed to upload file via STFP/SCP (.+?) -> (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/remote/src/transport/ssh.rs","lineNumber":1290,"sourceCode":"            let stderr = String::from_utf8_lossy(&output.stderr);\n            log::debug!(\n                \"failed to upload file via SFTP {src_path_display} -> {dest_path_str}: {stderr}\"\n            );\n        }\n\n        log::debug!(\"using SCP for file upload\");\n        let mut command = self.build_scp_command(src_path, &dest_path_str, None);\n        let output = command.output().await?;\n\n        if output.status.success() {\n            return Ok(());\n        }\n\n        let stderr = String::from_utf8_lossy(&output.stderr);\n        log::debug!(\n            \"failed to upload file via SCP {src_path_display} -> {dest_path_str}: {stderr}\",\n        );\n        anyhow::bail!(\n            \"failed to upload file via STFP/SCP {} -> {}: {}\",\n            src_path_display,\n            dest_path_str,\n            stderr,\n        );\n    }\n\n    async fn is_sftp_available() -> bool {\n        which::which(\"sftp\").is_ok()\n    }\n}\n\nimpl SshSocket {\n    #[cfg(not(windows))]\n    async fn new(options: SshConnectionOptions, socket_path: PathBuf) -> Result<Self> {\n        Ok(Self {\n            connection_options: options,\n            envs: HashMap::default(),","sourceCodeStart":1272,"sourceCodeEnd":1308,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/remote/src/transport/ssh.rs#L1272-L1308","documentation":"For single-file uploads over SSH, Zed tries SFTP and falls back to a plain scp command; when the scp fallback exits non-zero this error is raised with the CLI's stderr (the 'STFP' in the message is a source-level typo for SFTP). Neither SFTP nor SCP could transfer the file.","triggerScenarios":"build_scp_command's scp invocation exits non-zero for the uploaded file: scp missing on either side, permission denied on the destination, disk full, or remote shell startup output corrupting the SFTP/SCP protocol channel.","commonSituations":"Remotes without openssh-clients; destination dirs writable-but-not-owned or on full filesystems; .bashrc/.profile echoing text that breaks sftp's strict protocol; filenames needing shell quoting.","solutions":["Run scp manually with the same src/dst shown in the message to reproduce and read the stderr","Check remote writability and space: `df -h`, `touch <dest_dir>/probe`","Guard remote shell rc files against non-interactive output — any stdout noise breaks SFTP/SCP","Install openssh-client on the remote if scp/sftp binaries are missing"],"exampleFix":"# before: .bashrc prints a motd, sftp protocol desynchronizes\n# ~/.bashrc (remote)\necho \"welcome\"   # remove/guard for non-interactive shells\n\n# after\nif [ -z \"$PS1\" ]; then return; fi\necho \"welcome\"","handlingStrategy":"retry","validationCode":"async fn remote_accepts_uploads(socket: &SshSocket, shell: ShellKind, dest_dir: &str) -> bool {\n    socket.run_command(shell, \"which\", &[\"scp\"], true).await.is_ok()\n        && socket\n            .run_command(shell, \"touch\", &[&format!(\"{dest_dir}/probe\")], true)\n            .await\n            .is_ok()\n}","typeGuard":null,"tryCatchPattern":"match upload_file(src, dest).await {\n    Err(e) if e.to_string().contains(\"STFP/SCP\") && attempts_left() => {\n        // repair writability / shell noise, then retry the single-file upload once\n        retry_after_repair().await\n    }\n    other => other,\n}","preventionTips":["Install openssh-client on the remote so scp/sftp exist","Make rc files silent for non-interactive shells (SFTP protocol strictness)","Probe destination writability before large uploads"],"tags":["ssh","sftp","scp","file-transfer"],"backgroundTag":"scp-upload-failed","analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}