puppetlabs/puppet · error · Puppet::Util::Windows::Error
Failed to remove environment variable: %{name}
Error message
Failed to remove environment variable: %{name} What it means
Raised by set_environment_variable (lib/puppet/util/windows/process.rb:333) when the removal form of the API — SetEnvironmentVariableW(name, NULL) — returns FALSE. Windows answers with ERROR_ENVVAR_NOT_FOUND (203) when the variable is not present; other codes cover malformed names (embedded '=') or an environment the caller does not control. Removal is not idempotent at the Win32 level, so 'ensure absent' style workflows hit this naturally.
Source
Thrown at lib/puppet/util/windows/process.rb:333
end
.map { |env_pair| env_pair.split('=', 2) }
pairs.to_h
ensure
if env_ptr && !env_ptr.null?
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 elevatedView on GitHub (pinned to e227c27540)
Solutions
- Rescue Puppet::Util::Windows::Error and treat e.code == 203 (ERROR_ENVVAR_NOT_FOUND) as success for removal semantics.
- Check presence first via Process.get_environment_strings when you need explicit state transitions.
- Sanitize the name (no '=', sane length) before calling.
- For persistent machine/user variables, manage the registry environment keys and broadcast WM_SETTINGCHANGE instead of this per-process API.
Example fix
# before — raises when the variable is already absent
Process.set_environment_variable('MY_VAR', nil)
# after — idempotent removal
begin
Process.set_environment_variable('MY_VAR', nil)
rescue Puppet::Util::Windows::Error => e
raise unless e.code == 203 # ERROR_ENVVAR_NOT_FOUND — already gone
end Defensive patterns
Strategy: try-catch
Validate before calling
# only attempt removal when present present = Process.get_environment_strings.key?(name) Process.set_environment_variable(name, nil) if present
Try / catch
begin Process.set_environment_variable(name, nil) rescue Puppet::Util::Windows::Error => e raise unless e.code == 203 # ERROR_ENVVAR_NOT_FOUND # already absent — treat as success end
Prevention
- Treat code 203 as success in any 'ensure absent' logic
- Check presence with get_environment_strings before conditional workflows
- Remember this API only touches the calling process's environment, not the persisted machine/user set
When it happens
Trigger: Removing a variable that was never set or was already removed earlier in the run (code 203); a name containing '='; unconditional cleanup calls in idempotent provisioning.
Common situations: Cleanup or provisioning scripts that remove variables unconditionally; a race with another writer deleting the variable first; hosts with differing environment baselines.
Related errors
- ReplaceFile(#{target}, #{source})
- MoveFileEx(#{source}, #{target}, #{flags.to_s(8)})
- CreateSymbolicLink(#{symlink}, #{target}, #{flags.to_s(8)})
- GetFileAttributes(#{file_name})
- Failed to set file attributes
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/9ac942e983e58562.
Report an issue: GitHub.