puppetlabs/puppet · error · Puppet::Error

Invalid %{klass}: %{id}

Error message

Invalid %{klass}: %{id}

What it means

Raised by Puppet::Util::SUIDManager.convert_xid when a user or group name cannot be translated into an id. convert_xid is the shared helper behind change_group and change_user; it calls Puppet::Util.uid or Puppet::Util.gid, and raises this Puppet::Error when the lookup returns nil.

Source

Thrown at lib/puppet/util/suidmanager.rb:150

      initgroups(uid)
      Process.euid = uid
    else
      Process.euid = uid
      initgroups(uid)
    end
  end
  module_function :change_user

  # Make sure the passed argument is a number.
  def convert_xid(type, id)
    return id if id.is_a? Integer

    map = { :gid => :group, :uid => :user }
    raise ArgumentError, _("Invalid id type %{type}") % { type: type } unless map.include?(type)

    ret = Puppet::Util.send(type, id)
    if ret.nil?
      raise Puppet::Error, _("Invalid %{klass}: %{id}") % { klass: map[type], id: id }
    end

    ret
  end
  module_function :convert_xid

  # Initialize primary and supplemental groups to those of the target user.  We
  # take the UID and manually look up their details in the system database,
  # including username and primary group. This method will fail on Windows, or
  # if used without root to initgroups of another user.
  def initgroups(uid)
    pwent = Etc.getpwuid(uid)
    Process.initgroups(pwent.name, pwent.gid)
  end

  module_function :initgroups
end

View on GitHub (pinned to e227c27540)

Solutions

  1. Confirm the id resolves: `getent group <name>` / `getent passwd <name>`, then create the missing account or fix the typo.
  2. Order the catalog so users/groups are managed before the resources that drop privileges to them.
  3. Pass an Integer uid/gid to bypass name resolution entirely.

Example fix

# before
Puppet::Util::SUIDManager.change_group('appgrp') # raises Invalid group: appgrp

# after
gid = Puppet::Util.gid('appgrp') or raise ArgumentError, "group 'appgrp' missing"
Puppet::Util::SUIDManager.change_group(gid)
Defensive patterns

Strategy: validation

Validate before calling

def xid_resolves?(type, id)
  id.is_a?(Integer) || !Puppet::Util.send(type, id).nil?
end
raise ArgumentError, "#{id.inspect} does not resolve as #{type}" unless xid_resolves?(:gid, id)
Puppet::Util::SUIDManager.change_group(id)

Try / catch

begin
  Puppet::Util::SUIDManager.convert_xid(type, id)
rescue Puppet::Error, ArgumentError => e
  raise "cannot resolve #{type} #{id.inspect}: #{e.message}"
end

Prevention

When it happens

Trigger: Puppet::Util::SUIDManager.change_group('wheel') or change_user('puppet') where the name has no passwd/group entry, or any direct call like convert_xid(:gid, 'nonexistent') / convert_xid(:uid, 'ghost').

Common situations: Dropping privileges to an account or group that is created later in the catalog; minimal container images missing expected system groups; NSS/LDAP outages during the agent run.

Related errors


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