puppetlabs/puppet · error · Puppet::Error

Could not set %{param} on %{resource}[%{name}]: %{detail}

Error message

Could not set %{param} on %{resource}[%{name}]: %{detail}

What it means

Raised by nameservice.rb:274 when the modify command for a property (built by modifycmd after munge/validate, e.g. `usermod -s /bin/zsh <name>`) exits non-zero. It wraps the underlying Puppet::ExecutionFailure into Puppet::Error with the param, resource type, resource name and the command output as %{detail}. When the property is sensitive (has_sensitive_data? is true, e.g. passwords) the command output was already redacted by execute(:sensitive => true), so %{detail} will not leak the secret.

Source

Thrown at lib/puppet/provider/nameservice.rb:274

    @custom_environment = {}
    @objectinfo = nil
    if resource.is_a?(Hash) && !resource[:canonical_name].nil?
      @canonical_name = resource[:canonical_name]
    else
      @canonical_name = resource[:name]
    end
  end

  def set(param, value)
    self.class.validate(param, value)
    cmd = modifycmd(param, munge(param, value))
    raise Puppet::DevError, _("Nameservice command must be an array") unless cmd.is_a?(Array)

    sensitive = has_sensitive_data?(param)
    begin
      execute(cmd, { :failonfail => true, :combine => true, :custom_environment => @custom_environment, :sensitive => sensitive })
    rescue Puppet::ExecutionFailure => detail
      raise Puppet::Error, _("Could not set %{param} on %{resource}[%{name}]: %{detail}") % { param: param, resource: @resource.class.name, name: @resource.name, detail: detail }, detail.backtrace
    end
  end

  # Derived classes can override to declare sensitive data so a flag can be passed to execute
  def has_sensitive_data?(property = nil)
    false
  end

  # From overriding Puppet::Property#insync? Ruby Etc::getpwnam < 2.1.0 always
  # returns a struct with binary encoded string values, and >= 2.1.0 will return
  # binary encoded strings for values incompatible with current locale charset,
  # or Encoding.default_external if compatible. Compare a "should" value with
  # encoding of "current" value, to avoid unnecessary property syncs and
  # comparison of strings with different encodings. (PUP-6777)
  #
  # return basic string comparison after re-encoding (same as
  # Puppet::Property#property_matches)
  def comments_insync?(current, should)

View on GitHub (pinned to e227c27540)

Solutions

  1. Read %{detail} — it embeds the exact usermod/groupmod stderr. Run the same modifycmd by hand to reproduce.
  2. Fix the offending property value in the manifest (existing shell path, existing group, policy-compliant password).
  3. If the tool is missing, fix the provider confine or install the sysadmin package that provides usermod/groupmod.
  4. For password policy failures, generate a compliant hash or relax the policy; Puppet passes the hash verbatim.

Example fix

# before: usermod fails 'shell /bin/fish does not exist'
user { 'joe': shell => '/bin/fish' }

# after: point at a shell that exists on the node
user { 'joe': shell => '/bin/bash' }
Defensive patterns

Strategy: try-catch

Validate before calling

# dry-run the modify command for risky attributes
Puppet::Util.safe_posix_fork rescue nil
# simpler: validate values against the OS before the agent run
File.read('/etc/shells').include?('/bin/fish') or raise 'shell not present on node'

Try / catch

begin
  user { 'joe' => { shell: '/bin/fish' } }  # pseudo
rescue Puppet::Error => e
  raise unless e.message =~ /Could not set \S+ on \w+/
  # fall back to leaving the attribute unmanaged and file a report
  notify { "usermod failed: #{e.message}": }
end

Prevention

When it happens

Trigger: A property sync on a user/group/provider derived from Nameservice: usermod/groupmod failing due to invalid values accepted by Puppet but rejected by the OS (bad shell path not in /etc/shells, login class that does not exist, UID already in use when uniqueness tools run, password rejected by PAM/chpasswd policy), or the tool being missing/broken.

Common situations: Managing User['joe'] { shell => '/bin/fish' } on a node without /bin/fish installed; setting a password that violates system policy so `chpasswd`/usermod -p fails; AIX `chuser` rejecting a nonexistent group as primary; typo'd attribute values that pass Puppet validation but fail OS-level validation.

Related errors


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