hashicorp/packer · error

Error uploading script: %s

Error message

Error uploading script: %s

What it means

The provisioner uploads the script to the remote machine at config.RemotePath via the communicator (SSH/WinRM/Docker). If comm.Upload fails — connection dropped, permission denied, disk full, path not writable — Provision returns this error inside the retryable StartRetryTimeout loop. Because the upload is retried, transient disconnects are retried until the timeout is exhausted.

Source

Thrown at provisioner/shell/provisioner.go:335

		// Upload the file and run the command. Do this in the context of
		// a single retryable function so that we don't end up with
		// the case that the upload succeeded, a restart is initiated,
		// and then the command is executed but the file doesn't exist
		// any longer.
		var cmd *packersdk.RemoteCmd
		err = retry.Config{StartTimeout: p.config.StartRetryTimeout}.Run(ctx, func(ctx context.Context) error {
			if _, err := f.Seek(0, 0); err != nil {
				return err
			}

			var r io.Reader = f
			if !p.config.Binary {
				r = &UnixReader{Reader: r}
			}

			if err := comm.Upload(p.config.RemotePath, r, nil); err != nil {
				return fmt.Errorf("Error uploading script: %s", err)
			}

			cmd = &packersdk.RemoteCmd{
				Command: fmt.Sprintf("chmod 0755 %s", p.config.RemotePath),
			}
			if err := comm.Start(ctx, cmd); err != nil {
				return fmt.Errorf(
					"Error chmodding script file to 0755 in remote "+
						"machine: %s", err)
			}
			cmd.Wait()

			cmd = &packersdk.RemoteCmd{Command: command}
			return cmd.RunWithUi(ctx, comm, ui)
		})

		if err != nil {
			return err

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Verify the communicator connection is alive (ssh/winrm credentials, security groups, network ACLs)
  2. Check the remote path is writable and the filesystem has space (e.g. /tmp not full)
  3. Increase start_retry_timeout if the failure is transient during reboots
  4. Re-run the build; if it follows a rebooting provisioner, order it after restart completion or use expect_disconnect/retry logic

Example fix

// before (packer template)
provisioner "shell" {
  remote_path = "/root/not-writable/script.sh"
}
// after
provisioner "shell" {
  remote_path = "/tmp/script.sh"
  start_retry_timeout = "10m"
}
Defensive patterns

Strategy: retry

Validate before calling

# Before building, verify communicator reachability:
ssh -i key.pem user@host 'test -w /tmp && df -h /tmp'   # writable path + free space

Try / catch

err = retry.Config{StartTimeout: p.config.StartRetryTimeout}.Run(ctx, func(ctx context.Context) error {
    if _, err := f.Seek(0, 0); err != nil { return err }
    if err := comm.Upload(p.config.RemotePath, r, nil); err != nil {
        return fmt.Errorf("Error uploading script: %s", err)
    }
    return nil
})

Prevention

When it happens

Trigger: comm.Upload(p.config.RemotePath, r, nil) returning an error: SSH/WinRM connection failure mid-upload, remote path not writable (e.g. /tmp full or root-only), authentication failure, or remote host unreachable during provisioning.

Common situations: Remote machine rebooted by a previous provisioner so the connection is gone; /tmp on the instance full; SSH key rotated or agent disconnected; Windows communicators failing on path semantics for RemotePath; flaky network to a cloud VM.

Related errors


AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05). Data as JSON: /api/errors/53bb9dfa8b5a999c. Report an issue: GitHub.