puppetlabs/puppet · error · Puppet::Util::Windows::Error
OpenProcess(#{desired_access.to_s(8)}, #{inherit}, #{process
Error message
OpenProcess(#{desired_access.to_s(8)}, #{inherit}, #{process_id}) What it means
Raised by Process.open_process (lib/puppet/util/windows/process.rb:76) when the Win32 OpenProcess call returns a NULL handle; the message records the requested access mask (octal), the inherit flag and the pid. Typical codes: ERROR_ACCESS_DENIED (5) — the caller asked for more rights than it holds over the target — and ERROR_INVALID_PARAMETER (87) — the pid does not exist because the process already exited or was never valid.
Source
Thrown at lib/puppet/util/windows/process.rb:76
end
exit_status
end
module_function :wait_process
def get_current_process
# this pseudo-handle does not require closing per MSDN docs
GetCurrentProcess()
end
module_function :get_current_process
def open_process(desired_access, inherit_handle, process_id, &block)
phandle = nil
inherit = inherit_handle ? FFI::WIN32_TRUE : FFI::WIN32_FALSE
begin
phandle = OpenProcess(desired_access, inherit, process_id)
if phandle == FFI::Pointer::NULL_HANDLE
raise Puppet::Util::Windows::Error, "OpenProcess(#{desired_access.to_s(8)}, #{inherit}, #{process_id})"
end
yield phandle
ensure
FFI::WIN32.CloseHandle(phandle) if phandle
end
# phandle has had CloseHandle called against it, so nothing to return
nil
end
module_function :open_process
def open_process_token(handle, desired_access, &block)
token_handle = nil
begin
FFI::MemoryPointer.new(:handle, 1) do |token_handle_ptr|
result = OpenProcessToken(handle, desired_access, token_handle_ptr)
if result == FFI::WIN32_FALSEView on GitHub (pinned to e227c27540)
Solutions
- Treat it as a race first: when the pid is gone (e.code 87) skip or retry instead of failing.
- Request the least access that works — PROCESS_QUERY_LIMITED_INFORMATION (0x1000) succeeds where PROCESS_QUERY_INFORMATION is denied for same-user processes.
- Run elevated or under an account that can enable SeDebugPrivilege when inspecting other users' processes (Puppet wraps this in Security.with_privilege).
- Rescue Puppet::Util::Windows::Error and branch on e.code (5 vs 87) to distinguish permissions from dead pids.
Example fix
# before
Process.open_process(Process::PROCESS_QUERY_INFORMATION, false, pid) { |h| use(h) }
# after — accept a vanished process instead of raising
begin
Process.open_process(Process::PROCESS_QUERY_INFORMATION, false, pid) { |h| use(h) }
rescue Puppet::Util::Windows::Error => e
raise unless e.code == 87 # ERROR_INVALID_PARAMETER — process gone
nil
end Defensive patterns
Strategy: try-catch
Try / catch
begin
Process.open_process(access, false, pid) { |h| yield h }
rescue Puppet::Util::Windows::Error => e
return nil if e.code == 87 # pid gone — expected when racing process exit
return nil if e.code == 5 # access denied — skip protected/foreign processes
raise
end Prevention
- Ask for the narrowest access mask that suffices
- Re-check pid liveness immediately before opening and treat misses as skips
- Run inventory code as SYSTEM or elevated when crossing user sessions
- Never assume a pid from an earlier snapshot still exists
When it happens
Trigger: Requesting PROCESS_QUERY_INFORMATION (as get_process_image_name_by_pid does) on a process owned by another session/user without SE_DEBUG privilege; the target pid exiting between enumeration and open; opening a protected-process-light (PPL) binary; passing pid 0 or an invalid value.
Common situations: Process inventory or monitoring code racing short-lived processes; non-elevated agents inspecting elevated/SYSTEM processes; pid reuse between snapshot and open; security software protecting its processes.
Related errors
- QueryFullProcessImageNameW(phandle, #{use_win32_path_format}
- Failed to get child process exit code
- OpenProcessToken(#{handle}, #{desired_access.to_s(8)}, #{tok
- GetTokenInformation(#{token_handle}, #{token_information}, #
- ReplaceFile(#{target}, #{source})
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/21a16bb5171a8823.
Report an issue: GitHub.