puppetlabs/puppet · error · ArgumentError

File modes must be numbers

Error message

File modes must be numbers

What it means

Inside a {...} file-options block, the mode option must match /^\d+$/ after extraction (extract_fileinfo in lib/puppet/settings/config_file.rb:137); word-char values that are not purely digits — 0o644, 644x, rw — raise ArgumentError 'File modes must be numbers'. Symbolic modes (rwxr-xr-x) never reach this check because their dashes fail the param=value word regex and hit the generic parse error instead.

Source

Thrown at lib/puppet/settings/config_file.rb:137

  def empty_section
    { :_meta => {} }
  end

  def extract_fileinfo(string)
    result = {}
    value = string.sub(/\{\s*([^}]+)\s*\}/) do
      params = ::Regexp.last_match(1)
      params.split(/\s*,\s*/).each do |str|
        if str =~ /^\s*(\w+)\s*=\s*(\w+)\s*$/
          param = ::Regexp.last_match(1).intern
          value = ::Regexp.last_match(2)
          result[param] = value
          unless [:owner, :mode, :group].include?(param)
            raise ArgumentError, _("Invalid file option '%{parameter}'") % { parameter: param }
          end

          if param == :mode and value !~ /^\d+$/
            raise ArgumentError, _("File modes must be numbers")
          end
        else
          raise ArgumentError, _("Could not parse '%{string}'") % { string: string }
        end
      end
      ''
    end
    result[:value] = value.sub(/\s*$/, '')
    result
  end
end

View on GitHub (pinned to e227c27540)

Solutions

  1. Write modes as plain octal digits without prefix or quotes: mode = 0644, mode = 750.
  2. Fix templates that emit 0o-prefixed or symbolic strings for the mode option.
  3. Validate the whole {...} block by parsing the file once after generation.

Example fix

# before
vardir = /opt/puppet { owner = puppet, mode = 0o644 }

# after
vardir = /opt/puppet { owner = puppet, mode = 0644 }
Defensive patterns

Strategy: validation

Validate before calling

mode_value = '0644'
raise ArgumentError, 'mode must be digits only' unless mode_value =~ /^\d+$/

Type guard

numeric_mode = ->(v) { v.to_s.match?(/^\d+$/) }

Try / catch

begin
  Puppet::Settings::ConfigFile.parse_file(file, text, [])
rescue ArgumentError => e
  raise unless e.message.include?('File modes must be numbers')
  Puppet.err("write modes as plain octal digits, e.g. mode = 0644")
  raise
end

Prevention

When it happens

Trigger: `confdir = /etc/puppet { mode = 0o644 }` (Ruby-style octal prefix); `mode = rw`; `mode = 644a`; values like mode = -1 fail the earlier regex and raise the parse error instead.

Common situations: Developers writing Ruby/Python octal literals (0o644, 0o755) into config templates; symbolic-mode habits from chmod; typo'd modes.

Related errors


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