puppetlabs/puppet · error · Puppet::Error
Numeric modes must be in octal, not decimal!
Error message
Numeric modes must be in octal, not decimal!
What it means
Raised by symbolic_mode_to_int when the mode is an all-digit string that contains digits outside octal range (8 or 9). The check runs after the pure-octal pattern ^[0-7]+$ fails but ^\d+$ succeeds, so Puppet knows the value is numeric-but-decimal-looking and rejects it, matching chmod semantics.
Source
Thrown at lib/puppet/util/symbolic_file_mode.rb:57
# up the bits with values 4, 2, and 1. Omitted digits are assumed to be
# leading zeros."
case value
when Numeric
value.to_s(8)
when /^0?[0-7]{1,4}$/
value.to_i(8).to_s(8) # strip leading 0's
else
value
end
end
def symbolic_mode_to_int(modification, to_mode = 0, is_a_directory = false)
if modification.nil? or modification == ''
raise Puppet::Error, _("An empty mode string is illegal")
elsif modification =~ /^[0-7]+$/
return modification.to_i(8)
elsif modification =~ /^\d+$/
raise Puppet::Error, _("Numeric modes must be in octal, not decimal!")
end
fail _("non-numeric current mode (%{mode})") % { mode: to_mode.inspect } unless to_mode.is_a?(Numeric)
original_mode = {
's' => (to_mode & 0o7000) >> 9,
'u' => (to_mode & 0o0700) >> 6,
'g' => (to_mode & 0o0070) >> 3,
'o' => (to_mode & 0o0007) >> 0,
# Are there any execute bits set in the original mode?
'any x?' => (to_mode & 0o0111) != 0
}
final_mode = {
's' => original_mode['s'],
'u' => original_mode['u'],
'g' => original_mode['g'],
'o' => original_mode['o'],
}View on GitHub (pinned to e227c27540)
Solutions
- Rewrite the mode using octal digits only, e.g. '0644' or '0755'.
- Always quote mode values in manifests so they are not treated as decimal Integers.
- Check the value for 8/9 digits and typos in the copied source.
Example fix
# before
file { '/tmp/x': mode => '648' } # 8 is not an octal digit
# after
file { '/tmp/x': mode => '0644' } Defensive patterns
Strategy: validation
Validate before calling
s = mode.to_s
unless s.empty? || s =~ /^[0-7]+$/ || s =~ /^([ugoa]*)([-+=].*)$/
raise ArgumentError, "mode #{s.inspect} must be octal digits or symbolic"
end
Puppet::Util::SymbolicMode.symbolic_mode_to_int(s) Type guard
def octal_or_symbolic?(m) m = m.to_s !m.empty? && (m =~ /^[0-7]+$/ || m =~ /^([ugoa]*)([-+=].*)$/) ? true : false end
Prevention
- Always quote numeric modes and keep them octal.
- Prefer the 4-digit form ('0644') to make intent explicit.
- Add rspec examples for mode parsing in wrapper code.
When it happens
Trigger: symbolic_mode_to_int('0999') or a manifest with mode => '648' — any digit string containing 8 or 9. Related footgun: unquoted bare integers like mode => 644 are parsed as decimal by Ruby before reaching this code.
Common situations: Copy-pasted Windows-style or arbitrary numbers into mode attributes; confusion between '644' and '0644' (both legal) versus values containing 8/9; generating mode strings from arithmetic.
Related errors
- An empty mode string is illegal
- File modes must be numbers
- Missing action
- X only works with the '+' operator
- One or more file(s) specified did not exist: %{files}
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/102ab35c570a52f7.
Report an issue: GitHub.