puppetlabs/puppet · error · Puppet::Error
Could not delete %{resource} %{name}: %{detail}
Error message
Could not delete %{resource} %{name}: %{detail} What it means
Raised by the Puppet nameservice provider family (useradd/groupadd/pw and friends, lib/puppet/provider/nameservice.rb:182) when the system deletion command returned by deletecmd (e.g. userdel, groupdel) exits non-zero while removing an existing object. The provider first checks exists? and returns early with 'already absent' if the object is gone, so this error means the object exists but the OS refused to delete it. The original Puppet::ExecutionFailure text (stderr/stdout of the command) is interpolated as %{detail} and the original backtrace is chained.
Source
Thrown at lib/puppet/provider/nameservice.rb:182
if feature?(:manages_password_age) && (cmd = passcmd)
execute(cmd, { :failonfail => true, :combine => true, :custom_environment => @custom_environment, :sensitive => sensitive })
end
rescue Puppet::ExecutionFailure => detail
raise Puppet::Error, _("Could not create %{resource} %{name}: %{detail}") % { resource: @resource.class.name, name: @resource.name, detail: detail }, detail.backtrace
end
end
def delete
unless exists?
info _("already absent")
# the object already doesn't exist
return nil
end
begin
execute(deletecmd, { :failonfail => true, :combine => true, :custom_environment => @custom_environment })
rescue Puppet::ExecutionFailure => detail
raise Puppet::Error, _("Could not delete %{resource} %{name}: %{detail}") % { resource: @resource.class.name, name: @resource.name, detail: detail }, detail.backtrace
end
end
def ensure
if exists?
:present
else
:absent
end
end
# Does our object exist?
def exists?
!!getinfo(true)
end
# Retrieve a specific value by name.
def get(param)View on GitHub (pinned to e227c27540)
Solutions
- Read %{detail} in the message: it contains the exact userdel/groupdel stderr. Reproduce by running the same deletecmd manually as the same user (e.g. `sudo userdel <name>`).
- If the detail says the user is logged in or has running processes, terminate them (`pgrep -u <name>`, log out sessions, stop the service) before re-applying, or consciously use a force flag via a manual Exec if appropriate.
- For 'still has members' from groupdel, remove the members (or their primary group) first.
- Verify the provider's commands exist on the node (confine/os check) and that custom_environment does not strip PATH.
Example fix
# before: fails with 'user jboss is currently used by process 1234'
user { 'jboss': ensure => absent }
# after: stop the service first so the account is no longer in use
service { 'jboss': ensure => stopped, before => User['jboss'] }
user { 'jboss': ensure => absent } Defensive patterns
Strategy: try-catch
Validate before calling
# pre-check that the object can actually be deleted
name = 'jboss'
if Etc.getpwnam(name) rescue nil
busy = `pgrep -u #{name}`.strip.length > 0
warn "#{name} still has processes; delete will fail" if busy
end Try / catch
begin
Puppet::Type.type(:user).instances.each { |u| u.provider.flush if u.provider.respond_to?(:delete) }
rescue Puppet::Error => e
raise unless e.message.start_with?('Could not delete')
# keep catalog application going, report which object failed
Puppet.err("delete skipped: #{e.message}")
end Prevention
- Order service stop / process termination (before =>) ahead of ensure => absent user/group resources.
- Never delete groups while members reference them; clean memberships first.
- Monitor %{detail} in agent logs — userdel stderr pinpoints the blocker immediately.
When it happens
Trigger: Applying ensure => absent (or running `puppet resource user <name> ensure=absent`) for a user/group whose deletecmd fails: userdel reports 'user <name> is currently used by process N' or 'user <name> is currently logged in', groupdel reports 'group still has members', the command binary is missing from PATH, or @custom_environment breaks the execution.
Common situations: Deleting a service account while its processes are still running; trying to delete a group that still has users in /etc/group; LDAP/NSS-backed passwd entries that the local tool cannot remove; hardened systems where PATH is restricted via custom_environment.
Related errors
- Could not set %{param} on %{resource}[%{name}]: %{detail}
- Could not set %{property} on %{resource}[%{name}]: %{detail}
- puppet.tasks/invalid-metadata
- Invalid value %{value}: %{property} must be an Integer!
- Cannot have both 'forcelocal' and 'ia_load_module' at the sa
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/968f73ecf584a7c8.
Report an issue: GitHub.