hashicorp/packer · error

Script disconnected unexpectedly. If you expected your scrip

Error message

Script disconnected unexpectedly. If you expected your script to disconnect, i.e. from a restart, you can try adding `"expect_disconnect": true` or `"valid_exit_codes": [0, 2300218]` to the shell provisioner parameters.

What it means

After running the script, if its remote command reports exit status CmdDisconnect (2300218 — the sentinel for a dropped connection) and `expect_disconnect` is false, the provisioner treats the script as having failed: the connection dropped while the script ran (usually because the script rebooted the machine) and this was not declared. The message tells the user exactly which config keys to set to accept this behavior.

Source

Thrown at provisioner/shell/provisioner.go:360

				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
		}

		// If the exit code indicates a remote disconnect, fail unless
		// we were expecting it.
		if cmd.ExitStatus() == packersdk.CmdDisconnect {
			if !p.config.ExpectDisconnect {
				return fmt.Errorf("Script disconnected unexpectedly. " +
					"If you expected your script to disconnect, i.e. from a " +
					"restart, you can try adding `\"expect_disconnect\": true` " +
					"or `\"valid_exit_codes\": [0, 2300218]` to the shell " +
					"provisioner parameters.")
			}
		} else if err := p.config.ValidExitCode(cmd.ExitStatus()); err != nil {
			return err
		}

		if p.config.SkipClean {
			continue
		}

		// Delete the temporary file we created. We retry this a few times
		// since if the above rebooted we have to wait until the reboot
		// completes.
		if err := p.cleanupRemoteFile(p.config.RemotePath, comm); err != nil {
			return err

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Add expect_disconnect = true to the shell provisioner block if the script intentionally disconnects/reboots
  2. Add valid_exit_codes = [0, 2300218] to accept the disconnect exit code as success
  3. Split the script: run non-rebooting parts first, then use the windows-restart provisioner for reboots
  4. If the disconnect is unintended, fix the script so it does not kill the connection (e.g. nohup/background the restart)

Example fix

// before
provisioner "shell" {
  scripts = ["reboot.sh"]
}
// after
provisioner "shell" {
  scripts = ["reboot.sh"]
  expect_disconnect = true
}
Defensive patterns

Strategy: validation

Validate before calling

provisioner "shell" {
  scripts            = ["reboot.sh"]
  expect_disconnect  = true
  # or: valid_exit_codes = [0, 2300218]
}

Prevention

When it happens

Trigger: Running a shell script that restarts/reboots the remote machine (e.g. `shutdown -r`, `systemctl reboot`) without setting expect_disconnect = true, so the communicator reports CmdDisconnect after the script terminates the session.

Common situations: Scripts that reboot the host as part of setup (kernel updates, hostname changes, joining a domain); scripts that kill the SSH daemon; Windows machines rebooting under an SSH communicator; converting a previously-working script into one that disconnects.

Related errors


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