puppetlabs/puppet · error · ArgumentError
Expiry dates must be YYYY-MM-DD or the string "absent"
Error message
Expiry dates must be YYYY-MM-DD or the string "absent"
What it means
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).
Source
Thrown at lib/puppet/type/user.rb:460
if munge(val)
raise ArgumentError, _("User provider %{name} can not manage home directories") % { name: provider.class.name } if provider and !provider.class.manages_homedir?
end
end
end
newproperty(:expiry, :required_features => :manages_expiry) do
desc "The expiry date for this user. Provide as either the special
value `absent` to ensure that the account never expires, or as
a zero-padded YYYY-MM-DD format -- for example, 2010-02-19."
newvalues :absent
newvalues(/^\d{4}-\d{2}-\d{2}$/)
validate do |value|
if value.intern != :absent and value !~ /^\d{4}-\d{2}-\d{2}$/
# TRANSLATORS YYYY-MM-DD represents a date with a four-digit year, a two-digit month, and a two-digit day,
# TRANSLATORS separated by dashes.
raise ArgumentError, _("Expiry dates must be YYYY-MM-DD or the string \"absent\"")
end
end
end
# Autorequire the group, if it's around
autorequire(:group) do
autos = []
# autorequire primary group, if managed
obj = @parameters[:gid]
groups = obj.shouldorig if obj
if groups
groups = groups.collect { |group|
if group.is_a?(String) && group =~ /^\d+$/
Integer(group)
else
group
endView on GitHub (pinned to e227c27540)
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
Example fix
# before
user { 'alice':
ensure => present,
expiry => '2010/02/19',
}
# after
user { 'alice':
ensure => present,
expiry => '2010-02-19',
} Defensive patterns
Strategy: validation
Validate before calling
# Validate date shape before use
raise 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/) Type guard
def valid_expiry?(v)
s = v.to_s
s == 'absent' || s.match?(/\A\d{4}-\d{2}-\d{2}\z/)
end Prevention
- 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
When it happens
Trigger: `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.
Common situations: 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.
Related errors
- Password warning days must be provided as a number.
- Group names must be provided, not GID numbers.
- Group names must be provided as an array, not a comma-separa
- Group names must not be empty. If you want to specify "no gr
- User provider %{name} can not manage home directories
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/1d8205b8d6f9e963.
Report an issue: GitHub.