hashicorp/packer · error

Error opening powershell script: %s

Error message

Error opening powershell script: %s

What it means

After successfully stating the script, Provision opens it locally with os.Open to read its contents for upload. An open failure (permissions, file locked, deleted between Stat and Open) produces "Error opening powershell script: %s" and aborts provisioning.

Source

Thrown at provisioner/powershell/provisioner.go:375

	}

	// every provisioner run will only have one env var script file so lets add it first
	uploadedScripts := []string{p.config.RemoteEnvVarPath}
	for _, path := range scripts {
		ui.Say(fmt.Sprintf("Provisioning with powershell script: %s", path))

		log.Printf("Opening %s for reading", path)
		fi, err := os.Stat(path)
		if err != nil {
			return fmt.Errorf("Error stating powershell script: %s", err)
		}
		if os.IsPathSeparator(p.config.RemotePath[len(p.config.RemotePath)-1]) {
			// path is a directory
			p.config.RemotePath += filepath.Base(fi.Name())
		}
		f, err := os.Open(path)
		if err != nil {
			return fmt.Errorf("Error opening powershell script: %s", err)
		}
		defer f.Close()

		command, err := p.createCommandText()
		if err != nil {
			return fmt.Errorf("Error processing command: %s", err)
		}

		// 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
			}
			if err := comm.Upload(p.config.RemotePath, f, &fi); err != nil {

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Grant the packer process read permission on the script (chmod/chmod +r or icacls).
  2. Close programs or exclude the script from AV locking, then retry.
  3. Copy the script to a local path with normal permissions instead of reading from a network share.
  4. Run packer as a user with access to the scripts directory.

Example fix

// shell
// before: -rw-------  bootstrap.ps1 (packer runs as different user)
// after
chmod 644 scripts/bootstrap.ps1
Defensive patterns

Strategy: validation

Validate before calling

// Go, before Provision: verify readability
for _, p := range cfg.Scripts {
    f, err := os.Open(p)
    if err != nil {
        return fmt.Errorf("cannot read script %q: %w", p, err)
    }
    f.Close()
}

Try / catch

// Go
err := prov.Provision(ctx, ui, comm, genData)
if err != nil {
    if errors.Is(err, os.ErrPermission) || strings.Contains(err.Error(), "Error opening powershell script") {
        // fix permissions or re-run as a user with read access
    }
    return err
}

Prevention

When it happens

Trigger: Provision called with a stat-able script path whose os.Open fails — most commonly a permission denied or the file being locked by another process.

Common situations: File readable only by another user; running packer as a restricted service account; on Windows the .ps1 is locked by an editor or AV scanner; NFS/network share permission issues.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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