{"record":{"id":"1d8205b8d6f9e963","repo":"puppetlabs/puppet","slug":"expiry-dates-must-be-yyyy-mm-dd-or-the-string-abs","errorCode":null,"errorMessage":"Expiry dates must be YYYY-MM-DD or the string \"absent\"","messagePattern":"Expiry dates must be YYYY-MM-DD or the string \"absent\"","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/type/user.rb","lineNumber":460,"sourceCode":"        if munge(val)\n          raise ArgumentError, _(\"User provider %{name} can not manage home directories\") % { name: provider.class.name } if provider and !provider.class.manages_homedir?\n        end\n      end\n    end\n\n    newproperty(:expiry, :required_features => :manages_expiry) do\n      desc \"The expiry date for this user. Provide as either the special\n           value `absent` to ensure that the account never expires, or as\n           a zero-padded YYYY-MM-DD format -- for example, 2010-02-19.\"\n\n      newvalues :absent\n      newvalues(/^\\d{4}-\\d{2}-\\d{2}$/)\n\n      validate do |value|\n        if value.intern != :absent and value !~ /^\\d{4}-\\d{2}-\\d{2}$/\n          # TRANSLATORS YYYY-MM-DD represents a date with a four-digit year, a two-digit month, and a two-digit day,\n          # TRANSLATORS separated by dashes.\n          raise ArgumentError, _(\"Expiry dates must be YYYY-MM-DD or the string \\\"absent\\\"\")\n        end\n      end\n    end\n\n    # Autorequire the group, if it's around\n    autorequire(:group) do\n      autos = []\n\n      # autorequire primary group, if managed\n      obj = @parameters[:gid]\n      groups = obj.shouldorig if obj\n      if groups\n        groups = groups.collect { |group|\n          if group.is_a?(String) && group =~ /^\\d+$/\n            Integer(group)\n          else\n            group\n          end","sourceCodeStart":442,"sourceCodeEnd":478,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/type/user.rb#L442-L478","documentation":"Raised by the validate block of the `expiry` property on the `user` type. The property accepts exactly two forms: the symbol/string 'absent' (never expires) or a zero-padded date matching /^\\d{4}-\\d{2}-\\d{2}$/ (also declared via newvalues). Anything else — slashes, month names, ISO timestamps, 'never' — raises this ArgumentError. The property requires the provider feature :manages_expiry (useradd, pw, openbsd, aix).","triggerScenarios":"`user { 'alice': expiry => '2010/02/19' }`, `=> 'Feb 19 2010'`, `=> '2010-2-19'` (no zero padding), or `=> 'never'` instead of 'absent'; Hiera dates stored in locale-dependent formats.","commonSituations":"Dates coming from CMDBs in DD/MM/YYYY or epoch form; copy-paste from `chage -l` ('Feb 19, 2010'); template code formatting dates without strftime zero-padding.","solutions":["Use zero-padded YYYY-MM-DD: `expiry => '2010-02-19'`","Use the special value `expiry => absent` for accounts that never expire","Normalize in the profile: `expiry => strftime(String($ts), '%Y-%m-%d')` or pg_time-style conversion before passing through"],"exampleFix":"# before\nuser { 'alice':\n  ensure => present,\n  expiry => '2010/02/19',\n}\n\n# after\nuser { 'alice':\n  ensure => present,\n  expiry => '2010-02-19',\n}","handlingStrategy":"validation","validationCode":"# Validate date shape before use\nraise ArgumentError, 'expiry must be YYYY-MM-DD or absent' unless %w[absent].include?(v.to_s) || v.to_s.match?(/\\A\\d{4}-\\d{2}-\\d{2}\\z/)","typeGuard":"def valid_expiry?(v)\n  s = v.to_s\n  s == 'absent' || s.match?(/\\A\\d{4}-\\d{2}-\\d{2}\\z/)\nend","tryCatchPattern":null,"preventionTips":["Type profile parameters as Optional[Pattern[/\\d{4}-\\d{2}-\\d{2}/]] or Optional[Enum['absent']]","Generate dates with strftime('%Y-%m-%d') which zero-pads","Document 'absent' (not 'never') as the no-expiry value in data docs"],"tags":["puppet","user-resource","expiry","date-validation"],"backgroundTag":"date-format-validation","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}