{"record":{"id":"18e8a983a11eff59","repo":"hashicorp/packer","slug":"script-disconnected-unexpectedly-if-you-expected","errorCode":null,"errorMessage":"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.","messagePattern":"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\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"provisioner/shell/provisioner.go","lineNumber":360,"sourceCode":"\t\t\t\treturn fmt.Errorf(\n\t\t\t\t\t\"Error chmodding script file to 0755 in remote \"+\n\t\t\t\t\t\t\"machine: %s\", err)\n\t\t\t}\n\t\t\tcmd.Wait()\n\n\t\t\tcmd = &packersdk.RemoteCmd{Command: command}\n\t\t\treturn cmd.RunWithUi(ctx, comm, ui)\n\t\t})\n\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// If the exit code indicates a remote disconnect, fail unless\n\t\t// we were expecting it.\n\t\tif cmd.ExitStatus() == packersdk.CmdDisconnect {\n\t\t\tif !p.config.ExpectDisconnect {\n\t\t\t\treturn fmt.Errorf(\"Script disconnected unexpectedly. \" +\n\t\t\t\t\t\"If you expected your script to disconnect, i.e. from a \" +\n\t\t\t\t\t\"restart, you can try adding `\\\"expect_disconnect\\\": true` \" +\n\t\t\t\t\t\"or `\\\"valid_exit_codes\\\": [0, 2300218]` to the shell \" +\n\t\t\t\t\t\"provisioner parameters.\")\n\t\t\t}\n\t\t} else if err := p.config.ValidExitCode(cmd.ExitStatus()); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif p.config.SkipClean {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Delete the temporary file we created. We retry this a few times\n\t\t// since if the above rebooted we have to wait until the reboot\n\t\t// completes.\n\t\tif err := p.cleanupRemoteFile(p.config.RemotePath, comm); err != nil {\n\t\t\treturn err","sourceCodeStart":342,"sourceCodeEnd":378,"githubUrl":"https://github.com/hashicorp/packer/blob/eb36e3c3e48a036f3e8cc94087636ee72e1303c9/provisioner/shell/provisioner.go#L342-L378","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add expect_disconnect = true to the shell provisioner block if the script intentionally disconnects/reboots","Add valid_exit_codes = [0, 2300218] to accept the disconnect exit code as success","Split the script: run non-rebooting parts first, then use the windows-restart provisioner for reboots","If the disconnect is unintended, fix the script so it does not kill the connection (e.g. nohup/background the restart)"],"exampleFix":"// before\nprovisioner \"shell\" {\n  scripts = [\"reboot.sh\"]\n}\n// after\nprovisioner \"shell\" {\n  scripts = [\"reboot.sh\"]\n  expect_disconnect = true\n}","handlingStrategy":"validation","validationCode":"provisioner \"shell\" {\n  scripts            = [\"reboot.sh\"]\n  expect_disconnect  = true\n  # or: valid_exit_codes = [0, 2300218]\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Audit scripts for restart/shutdown/daemon-killing commands and set expect_disconnect for those steps","Prefer the windows-restart provisioner for reboots instead of ad-hoc scripts","Keep valid_exit_codes explicit when scripts intentionally return unusual codes","Split rebooting logic from normal provisioning into separate provisioner blocks"],"tags":["provisioner","shell","disconnect","reboot","exit-code"],"backgroundTag":"unexpected-remote-disconnect","analyzedSha":"eb36e3c3e48a036f3e8cc94087636ee72e1303c9","analyzedAt":"2026-09-05T13:20:43.127Z","contentChangedAt":"2026-09-05T13:20:43.127Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}