hashicorp/packer · error

Environment variable not in format 'key=value': %s

Error message

Environment variable not in format 'key=value': %s

What it means

Raised in the windows-shell provisioner's Prepare when an entry in the provisioner's `environment_vars` (Vars) is not a well-formed `key=value` string. Each var is split on the first '=' with strings.SplitN(kv, "=", 2); the error fires when there is no '=' at all or the key side is empty. This prevents generating broken `set VAR=...` shell lines on the guest.

Source

Thrown at provisioner/windows-shell/provisioner.go:132

			errors.New("Either a script file or inline script must be specified."))
	} else if len(p.config.Scripts) > 0 && p.config.Inline != nil {
		errs = packersdk.MultiErrorAppend(errs,
			errors.New("Only a script file or an inline script can be specified, not both."))
	}

	for _, path := range p.config.Scripts {
		if _, err := os.Stat(path); err != nil {
			errs = packersdk.MultiErrorAppend(errs,
				fmt.Errorf("Bad script '%s': %s", path, err))
		}
	}

	// Do a check for bad environment variables, such as '=foo', 'foobar'
	for _, kv := range p.config.Vars {
		vs := strings.SplitN(kv, "=", 2)
		if len(vs) != 2 || vs[0] == "" {
			errs = packersdk.MultiErrorAppend(errs,
				fmt.Errorf("Environment variable not in format 'key=value': %s", kv))
		}
	}

	return errs
}

// This function takes the inline scripts, concatenates them
// into a temporary file and returns a string containing the location
// of said file.
func extractScript(p *Provisioner) (string, error) {
	temp, err := tmp.File("windows-shell-provisioner")
	if err != nil {
		log.Printf("Unable to create temporary file for inline scripts: %s", err)
		return "", err
	}
	writer := bufio.NewWriter(temp)
	for _, command := range p.config.Inline {
		log.Printf("Found command: %s", command)

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Rewrite each environment_vars entry as `KEY=value`, e.g. environment_vars = ["MYVAR=foo"] instead of ["MYVAR"].
  2. Check interpolated template variables: ensure the key part resolves to a non-empty name (avoid "${var.name}=x" when var.name is empty).
  3. Remove empty strings from the environment_vars array in your HCL/JSON template.
  4. If the value legitimately needs '=', that is fine — only the key side before the first '=' must be non-empty.

Example fix

// before
provisioner "windows-shell" {
  environment_vars = ["HTTP_PROXY", "API_KEY=${var.key}"]
}
// after: every entry is key=value
provisioner "windows-shell" {
  environment_vars = ["HTTP_PROXY=http://proxy:8080", "API_KEY=${var.key}"]
}
Defensive patterns

Strategy: validation

Validate before calling

func validEnvVars(vars []string) error {
    for _, kv := range vars {
        parts := strings.SplitN(kv, "=", 2)
        if len(parts) != 2 || parts[0] == "" {
            return fmt.Errorf("env var not key=value: %q", kv)
        }
    }
    return nil
}

Try / catch

// catch at template lint time
if err := validEnvVars(cfg.EnvironmentVars); err != nil {
    return fmt.Errorf("windows-shell environment_vars invalid: %w", err)
}

Prevention

When it happens

Trigger: Prepare validation loops over p.config.Vars and appends this error for any string where SplitN yields fewer than 2 parts or vs[0] == "" — e.g. "FOO" (no '='), "=bar" (empty key), or "=value with spaces". windows-shell/provisioner.go:131-137.

Common situations: User writes environment_vars = ["MYVAR"] forgetting the value; template variable interpolation producing an empty key like "=${env.MISSING}"; copying a list of var names instead of key=value pairs; whitespace/newline typos in JSON/HCL arrays.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


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