puppetlabs/puppet · error · ArgumentError

Class name must be provided.

Error message

Class name must be provided.

What it means

Raised by the validate block of the `loginclass` property (:required_features => :manages_loginclass, provided by the OpenBSD user provider) on the `user` type. Login classes (login.conf(5)) are names like 'staff' or 'daemon'; a value matching /^\d+$/ is rejected as a numeric non-name. Note the message is generic ('Class name must be provided.') — it fires only for all-digit values, not for empty strings.

Source

Thrown at lib/puppet/type/user.rb:798

        return entry unless entry.match?(%r{^(?:~|%h)/})

        # if user doesn't exist (yet), ignore nonexistent homedir
        home = homedir
        return nil unless home

        # compiler freezes "value" so duplicate using a gsub, second mutating gsub! is then ok
        entry = entry.gsub(%r{^~/}, "#{home}/")
        entry.gsub!(%r{^%h/}, "#{home}/")
        entry
      end
    end

    newproperty(:loginclass, :required_features => :manages_loginclass) do
      desc "The name of login class to which the user belongs."

      validate do |value|
        if value =~ /^\d+$/
          raise ArgumentError, _("Class name must be provided.")
        end
      end
    end

    # Generate ssh_authorized_keys resources for purging. The key files are
    # taken from the purge_ssh_keys parameter. The generated resources inherit
    # all metaparameters from the parent user resource.
    #
    # @return [Array<Puppet::Type::Ssh_authorized_key] a list of resources
    #   representing the found keys
    # @see generate
    # @api private
    def find_unmanaged_keys
      self[:purge_ssh_keys]
        .select { |f| File.readable?(f) }
        .map { |f| unknown_keys_in_file(f) }
        .flatten.each do |res|
          res[:ensure] = :absent

View on GitHub (pinned to e227c27540)

Solutions

  1. Pass the login.conf class name: `loginclass => 'staff'`
  2. Verify valid names in /etc/login.conf on the target host
  3. Remove numeric values from the source data

Example fix

# before
user { 'alice':
  ensure      => present,
  loginclass  => '0',
}

# after
user { 'alice':
  ensure      => present,
  loginclass  => 'staff',
}
Defensive patterns

Strategy: validation

Validate before calling

raise ArgumentError, 'loginclass must be a login.conf name' if loginclass.to_s.match?(/\A\d+\z/)

Type guard

def loginclass_name?(v)
  v.is_a?(String) && !v.match?(/\A\d+\z/)
end

Prevention

When it happens

Trigger: `user { 'alice': loginclass => '0' }` on OpenBSD; numeric login.conf stanza identifiers from generated data; defaults copied from a spreadsheet's numeric class column.

Common situations: Automated manifests built from tabular data; misunderstanding loginclass as a class ID rather than a login.conf name; only relevant on OpenBSD since only its provider declares manages_loginclass.

Related errors


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