{"record":{"id":"abda23af37fb14bd","repo":"puppetlabs/puppet","slug":"group-names-must-be-provided-as-an-array-not-a-co","errorCode":null,"errorMessage":"Group names must be provided as an array, not a comma-separated list.","messagePattern":"Group names must be provided as an array, not a comma-separated list\\.","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/type/user.rb","lineNumber":349,"sourceCode":"      end\n\n      validate do |value|\n        if value.to_s !~ /^-?\\d+$/\n          raise ArgumentError, \"Password warning days must be provided as a number.\"\n        end\n      end\n    end\n\n    newproperty(:groups, :parent => Puppet::Property::List) do\n      desc \"The groups to which the user belongs.  The primary group should\n        not be listed, and groups should be identified by name rather than by\n        GID.  Multiple groups should be specified as an array.\"\n\n      validate do |value|\n        if value =~ /^\\d+$/\n          raise ArgumentError, _(\"Group names must be provided, not GID numbers.\")\n        end\n        raise ArgumentError, _(\"Group names must be provided as an array, not a comma-separated list.\") if value.include?(\",\")\n        raise ArgumentError, _(\"Group names must not be empty. If you want to specify \\\"no groups\\\" pass an empty array\") if value.empty?\n      end\n\n      def change_to_s(currentvalue, newvalue)\n        newvalue = newvalue.split(\",\") if newvalue != :absent\n\n        if provider.respond_to?(:groups_to_s)\n          # for Windows ADSI\n          # de-dupe the \"newvalue\" when the sync event message is generated,\n          # due to final retrieve called after the resource has been modified\n          newvalue = provider.groups_to_s(newvalue).split(',').uniq\n        end\n\n        super(currentvalue, newvalue)\n      end\n\n      # override Puppet::Property::List#retrieve\n      def retrieve","sourceCodeStart":331,"sourceCodeEnd":367,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/type/user.rb#L331-L367","documentation":"Raised by the validate block of the `groups` property on the `user` type when a member string contains a comma. The property descends from Puppet::Property::List and expects an array of group names; a single comma-joined string is explicitly rejected so that 'a,b' is never treated as one weird group name. The comma check runs after the numeric check, so '1,2' raises the GID error first.","triggerScenarios":"`user { 'alice': groups => 'wheel,audio' }`; a template or Hiera lookup that joins an array with join(','); passing output of `id -Gn` verbatim.","commonSituations":"Refactoring shell scripts that used `usermod -G wheel,audio`; string interpolation of a Ruby array into a manifest; ENC/classifier APIs that only accept strings for parameters.","solutions":["Pass a real array: `groups => ['wheel', 'audio']`","In Hiera store a YAML list, not a comma-joined string","If the value arrives as a string, split it before use: `groups => $raw.split(',')`"],"exampleFix":"# before\nuser { 'alice':\n  ensure => present,\n  groups => 'wheel,audio',\n}\n\n# after\nuser { 'alice':\n  ensure => present,\n  groups => ['wheel', 'audio'],\n}","handlingStrategy":"validation","validationCode":"# Normalize incoming data before the user resource\n$group_list = $raw_groups ? {\n  String => $raw_groups.split(','),\n  default => $raw_groups,\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always author groups as Puppet arrays, never comma-joined scalars","In Ruby callers, Array(value) a scalar before passing","Prefer deep_merge/lookup with arrays kept as sequences"],"tags":["puppet","user-resource","groups","list-validation"],"backgroundTag":"string-list-instead-of-array","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}