{"record":{"id":"441d2e63e10e6322","repo":"hashicorp/packer","slug":"error-opening-shell-script-s-441d2e","errorCode":null,"errorMessage":"Error opening shell script: %s","messagePattern":"Error opening shell script: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"provisioner/windows-shell/provisioner.go","lineNumber":187,"sourceCode":"\tp.generatedData = generatedData\n\n\tif p.config.Inline != nil {\n\t\ttemp, err := extractScript(p)\n\t\tif err != nil {\n\t\t\tui.Error(fmt.Sprintf(\"Unable to extract inline scripts into a file: %s\", err))\n\t\t}\n\t\tscripts = append(scripts, temp)\n\t\t// Remove temp script containing the inline commands when done\n\t\tdefer os.Remove(temp)\n\t}\n\n\tfor _, path := range scripts {\n\t\tui.Say(fmt.Sprintf(\"Provisioning with shell script: %s\", path))\n\n\t\tlog.Printf(\"Opening %s for reading\", path)\n\t\tf, err := os.Open(path)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"Error opening shell script: %s\", err)\n\t\t}\n\t\tdefer f.Close()\n\n\t\t// Create environment variables to set before executing the command\n\t\tflattenedVars := p.createFlattenedEnvVars()\n\n\t\t// Compile the command\n\t\tp.config.ctx.Data = &ExecuteCommandTemplate{\n\t\t\tVars: flattenedVars,\n\t\t\tPath: p.config.RemotePath,\n\t\t}\n\t\tcommand, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"Error processing command: %s\", err)\n\t\t}\n\n\t\t// Upload the file and run the command. Do this in the context of\n\t\t// a single retryable function so that we don't end up with","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/hashicorp/packer/blob/eb36e3c3e48a036f3e8cc94087636ee72e1303c9/provisioner/windows-shell/provisioner.go#L169-L205","documentation":"Raised in the windows-shell provisioner's Provision when a script file selected for provisioning cannot be opened on the host with os.Open. Provision resolves the script list (inline-generated temp script or configured `scripts`), then opens each file to upload it to the guest; any open failure is wrapped as \"Error opening shell script: %s\" with the original OS error. Unlike the Prepare-time stat check, this runs during the build, so paths that vanished or became unreadable between validation and provisioning land here.","triggerScenarios":"Provision loops over `scripts` and calls os.Open(path) for each; the call returns an error because the file was deleted or renamed after Prepare, permissions changed, or the path is a directory — provisioner.go:185-189. Also triggered for the temp script path if extractScript output was removed mid-build.","commonSituations":"Script deleted by a prior build step or tmp cleaner between validation and provisioning; relative path broken because the build changed working directory (e.g. running packer from a different cwd than intended); permissions tightened on a shared CI workspace; antivirus locking/removing the file.","solutions":["Re-check the path exists at build time (not just validation): `ls -l <path>` immediately before `packer build` and use `${path.root}` in HCL2 to make paths absolute.","Fix file permissions so the user running Packer can read the script.","Ensure no earlier provisioner or cleanup step deletes the script directory mid-build.","Re-run `packer validate` after any file moves so validation catches it up front."],"exampleFix":"// before: relative path breaks when cwd differs\nscripts = [\"setup.bat\"]\n// after\nscripts = [\"${path.root}/scripts/setup.bat\"]","handlingStrategy":"validation","validationCode":"for _, s := range scripts {\n    f, err := os.Open(s)\n    if err != nil { return fmt.Errorf(\"pre-open check failed for %q: %w\", s, err) }\n    f.Close()\n}","typeGuard":null,"tryCatchPattern":"if strings.Contains(err.Error(), \"Error opening shell script\") {\n    // fail fast before guest work; do not retry cloud-side\n    return fmt.Errorf(\"host-side script unreadable: %w\", err)\n}","preventionTips":["Use ${path.root}-anchored absolute paths in templates.","Don't mutate or clean the scripts directory during the build.","Verify file read permissions for the packer process user.","Keep scripts inside the repo working tree committed for CI."],"tags":["provisioner","windows","file-not-found","permissions"],"backgroundTag":"script-file-not-found","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"}