puppetlabs/puppet · error · Puppet::ExecutionFailure
Execution of '%{str}' returned %{exit_status}: %{output}
Error message
Execution of '%{str}' returned %{exit_status}: %{output} What it means
On Windows, Puppet::Util.execute launches the process via the Win32 API and collects its exit status; when failonfail is true and the status is non-zero it raises Puppet::ExecutionFailure including the command string, the numeric exit status, and the stripped stdout/stderr output. It is the Windows counterpart of the POSIX ExecutionFailure and carries the same meaning: the external command failed.
Source
Thrown at lib/puppet/util/execution.rb:312
rescue
nil
end
}
exit_status = Puppet::Util::Windows::Process.wait_process(process_info.process_handle)
# read output in if required
unless options[:squelch]
output = wait_for_output(stdout)
Puppet.warning _("Could not get output") unless output
end
ensure
FFI::WIN32.CloseHandle(process_info.process_handle)
FFI::WIN32.CloseHandle(process_info.thread_handle)
end
end
if options[:failonfail] and exit_status != 0
raise Puppet::ExecutionFailure, _("Execution of '%{str}' returned %{exit_status}: %{output}") % { str: command_str, exit_status: exit_status, output: output.strip }
end
ensure
# Make sure all handles are closed in case an exception was thrown attempting to execute.
[stdin, stdout, stderr].each { |io|
begin
io.close
rescue
nil
end
}
unless options[:squelch]
# if we opened a pipe, we need to clean it up.
reader.close if reader
stdout.close! if stdout && Puppet::Util::Platform.windows?
end
end
Puppet::Util::Execution::ProcessOutput.new(output || '', exit_status)View on GitHub (pinned to e227c27540)
Solutions
- Re-run the exact command in the same shell as the same account and check %ERRORLEVEL% to see the real failure
- Rescue Puppet::ExecutionFailure and branch on the exit code embedded in the message text
- Pass failonfail: false when non-zero exits are an expected outcome and inspect the output
- Run the agent/service under an account with the privileges the command needs
Example fix
# before
Puppet::Util.execute('net localgroup Developers alice /add')
# => Puppet::ExecutionFailure: Execution of 'net localgroup ...' returned 2: The account already exists ...
# after
begin
Puppet::Util.execute('net localgroup Developers alice /add')
rescue Puppet::ExecutionFailure => e
code = e.message[/returned (\d+):/, 1]&.to_i
raise unless [0, 1378].include?(code) # 1378 = already a member
end Defensive patterns
Strategy: try-catch
Validate before calling
unless Puppet::Util.which('net.exe')
raise ArgumentError, 'net.exe not found on PATH'
end Try / catch
begin Puppet::Util.execute(cmd) rescue Puppet::ExecutionFailure => e code = e.message[/returned (\d+):/, 1]&.to_i raise unless [0, 2].include?(code) end
Prevention
- Rescue Puppet::ExecutionFailure on Windows; the exit code is embedded in the message text
- Test commands interactively as the same account the Puppet service runs under
- Use failonfail: false for commands where failure is an expected branch
When it happens
Trigger: Running a failing .bat/.exe/PowerShell command through Puppet on Windows with the default failonfail: true — net.exe returning 2, msiexec returning 1603, or a PowerShell one-liner exiting with a script-set code.
Common situations: Windows package installs (msiexec error codes), net/user commands failing due to missing privileges, batch scripts that exit non-zero by design, and running under a restricted service account.
Related errors
- output.to_s
- Working directory %{cwd} does not exist!
- Request to Puppet Forge failed. Detail: %{detail}.
- RegisterEventSourceW failed to open Windows eventlog
- ReportEventW failed to report event to Windows eventlog
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/d3d09d23f4c9fe17.
Report an issue: GitHub.