puppetlabs/puppet · error · Puppet::Util::Windows::Error

Failed to set environment variable: %{name}

Error message

Failed to set environment variable: %{name}

What it means

Raised by set_environment_variable (lib/puppet/util/windows/process.rb:338) when SetEnvironmentVariableW(name, value) returns FALSE while setting (not removing) a variable. Typical causes: name or value exceeding the 32,767-character environment limit, an '=' embedded in the name, or the process environment block being exhausted by bulk updates.

Source

Thrown at lib/puppet/util/windows/process.rb:338

      if FreeEnvironmentStringsW(env_ptr) == FFI::WIN32_FALSE
        Puppet.debug "FreeEnvironmentStringsW memory leak"
      end
    end
  end
  module_function :get_environment_strings

  def set_environment_variable(name, val)
    raise Puppet::Util::Windows::Error(_('environment variable name must not be nil or empty')) if !name || name.empty?

    FFI::MemoryPointer.from_string_to_wide_string(name) do |name_ptr|
      if val.nil?
        if SetEnvironmentVariableW(name_ptr, FFI::MemoryPointer::NULL) == FFI::WIN32_FALSE
          raise Puppet::Util::Windows::Error, _("Failed to remove environment variable: %{name}") % { name: name }
        end
      else
        FFI::MemoryPointer.from_string_to_wide_string(val) do |val_ptr|
          if SetEnvironmentVariableW(name_ptr, val_ptr) == FFI::WIN32_FALSE
            raise Puppet::Util::Windows::Error, _("Failed to set environment variable: %{name}") % { name: name }
          end
        end
      end
    end
  end
  module_function :set_environment_variable

  def get_system_default_ui_language
    GetSystemDefaultUILanguage()
  end
  module_function :get_system_default_ui_language

  # Returns whether or not the OS has the ability to set elevated
  # token information.
  #
  # Returns true on Windows Vista or later, otherwise false
  #
  def supports_elevated_security?

View on GitHub (pinned to e227c27540)

Solutions

  1. Validate sizes before the call: keep name and value under 32K characters each.
  2. Move oversized payloads to a temp file and pass the path via the env var.
  3. Reject or sanitize '=' in names and strip stray whitespace.
  4. Log name/value lengths when it fires to confirm the limit is the cause.

Example fix

# before
Process.set_environment_variable(name, huge_json)

# after — spill to a file when the value is large
if value.length > 32_000
  file = File.join(Dir.tmpdir, "#{name}.payload")
  File.write(file, value)
  Process.set_environment_variable(name, file)
else
  Process.set_environment_variable(name, value)
end
Defensive patterns

Strategy: validation

Validate before calling

raise ArgumentError, 'env name invalid' if name.empty? || name.include?('=')
raise ArgumentError, "env value too long (#{value.length})" if value.length > 32_767
Process.set_environment_variable(name, value)

Type guard

settable_env_pair = ->(n, v) { n.is_a?(String) && !n.empty? && !n.include?('=') && v.is_a?(String) && v.length <= 32_767 }

Prevention

When it happens

Trigger: Writing very long values (serialized JSON, giant PATH-style strings, tokens) into a variable; names assembled from unvalidated input containing '='; hundreds of variables set in one run hitting environment block limits.

Common situations: CI/build runners pushing credentials or payloads through env vars; Puppet providers exporting large environment blocks to child processes; secrets managers overflowing into env values.

Related errors


AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21). Data as JSON: /api/errors/c00cb03aed678cc7. Report an issue: GitHub.