hashicorp/packer · warning

Error removing temporary script at %s!

Error message

Error removing temporary script at %s!

What it means

After the `rm -f` command runs successfully (connection intact), the provisioner checks its exit status; a non-zero status means the remote shell could not delete the temporary script, and this error is raised (and retried by the enclosing retry loop). Because the command is `rm -f`, this usually indicates permission problems on the remote path rather than a missing file.

Source

Thrown at provisioner/shell/provisioner.go:414

func (p *Provisioner) cleanupRemoteFile(path string, comm packersdk.Communicator) error {
	ctx := context.TODO()
	err := retry.Config{StartTimeout: p.config.StartRetryTimeout}.Run(ctx, func(ctx context.Context) error {
		cmd := &packersdk.RemoteCmd{
			Command: fmt.Sprintf("rm -f %s", path),
		}
		if err := comm.Start(ctx, cmd); err != nil {
			return fmt.Errorf(
				"Error removing temporary script at %s: %s",
				path, err)
		}
		cmd.Wait()
		// treat disconnects as retryable by returning an error
		if cmd.ExitStatus() == packersdk.CmdDisconnect {
			return fmt.Errorf("Disconnect while removing temporary script.")
		}
		if cmd.ExitStatus() != 0 {
			return fmt.Errorf(
				"Error removing temporary script at %s!",
				path)
		}
		return nil
	})

	if err != nil {
		return err
	}

	return nil
}

func (p *Provisioner) escapeEnvVars() ([]string, map[string]string) {
	envVars := make(map[string]string)

	// Always available Packer provided env vars
	envVars["PACKER_BUILD_NAME"] = p.config.PackerBuildName

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Set remote_path to a directory writable by the communicator user (e.g. /tmp/script.sh)
  2. Check remote permissions/ownership of the uploaded file and its directory
  3. Set skip_clean = true if leaving the temp file is harmless for your image
  4. SSH in manually and run `rm -f <path>` to see the underlying shell error

Example fix

// before
provisioner "shell" {
  remote_path = "/root/packer-shell/script.sh"
}
// after
provisioner "shell" {
  remote_path = "/tmp/packer-shell/script.sh"
}
Defensive patterns

Strategy: validation

Validate before calling

# Ensure the communicator user can delete the remote path:
ssh user@host 'test -w $(dirname /tmp/packer-shell/script.sh) && echo writable'

Try / catch

if cmd.ExitStatus() != 0 {
    return fmt.Errorf("Error removing temporary script at %s!", path) // retried, then surfaced
}

Prevention

When it happens

Trigger: comm.Start succeeds and cmd.Wait returns, but cmd.ExitStatus() != 0 for `rm -f <path>` — e.g. the file is owned by another user, the directory is not writable, or a shell-level error occurred on the remote host.

Common situations: RemotePath placed in a root-owned directory while the SSH user is unprivileged; immutable/read-only filesystem; SELinux or AppArmor policies blocking deletion; path with characters interpreted oddly by the remote shell.

Related errors


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