{"record":{"id":"2815bc910fc208b8","repo":"hashicorp/terraform","slug":"scp-failed-to-start-this-usually-means-that-scp-i","errorCode":null,"errorMessage":"SCP failed to start. This usually means that SCP is not\nproperly installed on the remote system.","messagePattern":"SCP failed to start\\. This usually means that SCP is not\nproperly installed on the remote system\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/communicator/ssh/communicator.go","lineNumber":613,"sourceCode":"\tlog.Println(\"[DEBUG] Waiting for SSH session to complete.\")\n\terr = session.Wait()\n\n\t// log any stderr before exiting on an error\n\tscpErr := stderr.String()\n\tif len(scpErr) > 0 {\n\t\tlog.Printf(\"[ERROR] scp stderr: %q\", stderr)\n\t}\n\n\tif err != nil {\n\t\tif exitErr, ok := err.(*ssh.ExitError); ok {\n\t\t\t// Otherwise, we have an ExitErorr, meaning we can just read\n\t\t\t// the exit status\n\t\t\tlog.Printf(\"[ERROR] %s\", exitErr)\n\n\t\t\t// If we exited with status 127, it means SCP isn't available.\n\t\t\t// Return a more descriptive error for that.\n\t\t\tif exitErr.ExitStatus() == 127 {\n\t\t\t\treturn errors.New(\n\t\t\t\t\t\"SCP failed to start. This usually means that SCP is not\\n\" +\n\t\t\t\t\t\t\"properly installed on the remote system.\")\n\t\t\t}\n\t\t}\n\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n// checkSCPStatus checks that a prior command sent to SCP completed\n// successfully. If it did not complete successfully, an error will\n// be returned.\nfunc checkSCPStatus(r *bufio.Reader) error {\n\tcode, err := r.ReadByte()\n\tif err != nil {\n\t\treturn err","sourceCodeStart":595,"sourceCodeEnd":631,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/communicator/ssh/communicator.go#L595-L631","documentation":"Returned by the SCP upload/download path when the remote `scp` command exits with status 127 (command not found). The communicator maps 127 specifically to this human-readable error explaining SCP is missing or not on PATH on the remote host.","triggerScenarios":"`scp -rvd <dst>` (or the download variant) is run over the SSH session and the remote shell returns exit 127 — `scp` binary is absent or not in PATH for the SSH user's non-interactive shell.","commonSituations":"Minimal/container remote images without openssh-clients; a non-login SSH shell whose PATH differs from the interactive one and omits `/usr/bin/scp`; stripped-down appliances.","solutions":["Install an SCP provider on the remote: `apt-get install openssh-client` / `yum install openssh-clients` / the alpine `openssh-client` package.","Ensure the SSH user's non-interactive PATH includes the directory containing `scp` (set it in `.bashrc`/`.ssh/environment` with `PermitUserEnvironment`).","If SCP cannot be installed, switch the connection `type` to `winrm` (Windows) or avoid file uploads for this host."],"exampleFix":"# before: connection { type = \"ssh\" } to a host without scp -> error on file upload\n# after: install openssh-client on the remote, e.g.\n#   sudo apt-get update && sudo apt-get install -y openssh-client","handlingStrategy":"validation","validationCode":"// Probe for scp before relying on file uploads (run over an existing session):\n//   ssh <host> \"command -v scp >/dev/null 2>&1 && echo ok || echo missing\"\n// If 'missing', install openssh-client on the remote first.","typeGuard":null,"tryCatchPattern":"if err := comm.Upload(dst, src); err != nil {\n    if strings.Contains(err.Error(), \"SCP failed to start\") {\n        return fmt.Errorf(\"scp missing on remote host %q: install openssh-client\", host)\n    }\n    return err\n}","preventionTips":["Bake openssh-client into base images used as Terraform provisioner targets.","Ensure the SSH user's non-interactive PATH includes /usr/bin.","Prefer the `file`/`remote-exec` provisioners only on hosts you control and can provision SCP on."],"tags":["ssh","scp","communicator","remote-host","missing-binary","provisioner"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}