hashicorp/terraform · error

SCP failed to start. This usually means that SCP is…

Error message

SCP failed to start. This usually means that SCP is not
properly installed on the remote system.

What it means

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.

Solutions

  1. Install an SCP provider on the remote: `apt-get install openssh-client` / `yum install openssh-clients` / the alpine `openssh-client` package.
  2. Ensure the SSH user's non-interactive PATH includes the directory containing `scp` (set it in `.bashrc`/`.ssh/environment` with `PermitUserEnvironment`).
  3. If SCP cannot be installed, switch the connection `type` to `winrm` (Windows) or avoid file uploads for this host.

Example fix

# before: connection { type = "ssh" } to a host without scp -> error on file upload
# after: install openssh-client on the remote, e.g.
#   sudo apt-get update && sudo apt-get install -y openssh-client
Defensive patterns

Strategy: validation

Validate before calling

// Probe for scp before relying on file uploads (run over an existing session):
//   ssh <host> "command -v scp >/dev/null 2>&1 && echo ok || echo missing"
// If 'missing', install openssh-client on the remote first.

Try / catch

if err := comm.Upload(dst, src); err != nil {
    if strings.Contains(err.Error(), "SCP failed to start") {
        return fmt.Errorf("scp missing on remote host %q: install openssh-client", host)
    }
    return err
}

Prevention

When it happens

Trigger: `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.

Common situations: 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.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/2815bc910fc208b8. Report an issue: GitHub.

Appendix: source

Thrown at internal/communicator/ssh/communicator.go:613

	log.Println("[DEBUG] Waiting for SSH session to complete.")
	err = session.Wait()

	// log any stderr before exiting on an error
	scpErr := stderr.String()
	if len(scpErr) > 0 {
		log.Printf("[ERROR] scp stderr: %q", stderr)
	}

	if err != nil {
		if exitErr, ok := err.(*ssh.ExitError); ok {
			// Otherwise, we have an ExitErorr, meaning we can just read
			// the exit status
			log.Printf("[ERROR] %s", exitErr)

			// If we exited with status 127, it means SCP isn't available.
			// Return a more descriptive error for that.
			if exitErr.ExitStatus() == 127 {
				return errors.New(
					"SCP failed to start. This usually means that SCP is not\n" +
						"properly installed on the remote system.")
			}
		}

		return err
	}

	return nil
}

// checkSCPStatus checks that a prior command sent to SCP completed
// successfully. If it did not complete successfully, an error will
// be returned.
func checkSCPStatus(r *bufio.Reader) error {
	code, err := r.ReadByte()
	if err != nil {
		return err

View on GitHub (pinned to d32a084675)