{"record":{"id":"0bc308822df2fb6a","repo":"puppetlabs/puppet","slug":"file-modes-must-be-numbers","errorCode":null,"errorMessage":"File modes must be numbers","messagePattern":"File modes must be numbers","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/settings/config_file.rb","lineNumber":137,"sourceCode":"  def empty_section\n    { :_meta => {} }\n  end\n\n  def extract_fileinfo(string)\n    result = {}\n    value = string.sub(/\\{\\s*([^}]+)\\s*\\}/) do\n      params = ::Regexp.last_match(1)\n      params.split(/\\s*,\\s*/).each do |str|\n        if str =~ /^\\s*(\\w+)\\s*=\\s*(\\w+)\\s*$/\n          param = ::Regexp.last_match(1).intern\n          value = ::Regexp.last_match(2)\n          result[param] = value\n          unless [:owner, :mode, :group].include?(param)\n            raise ArgumentError, _(\"Invalid file option '%{parameter}'\") % { parameter: param }\n          end\n\n          if param == :mode and value !~ /^\\d+$/\n            raise ArgumentError, _(\"File modes must be numbers\")\n          end\n        else\n          raise ArgumentError, _(\"Could not parse '%{string}'\") % { string: string }\n        end\n      end\n      ''\n    end\n    result[:value] = value.sub(/\\s*$/, '')\n    result\n  end\nend\n","sourceCodeStart":119,"sourceCodeEnd":149,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/settings/config_file.rb#L119-L149","documentation":"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.","triggerScenarios":"`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.","commonSituations":"Developers writing Ruby/Python octal literals (0o644, 0o755) into config templates; symbolic-mode habits from chmod; typo'd modes.","solutions":["Write modes as plain octal digits without prefix or quotes: mode = 0644, mode = 750.","Fix templates that emit 0o-prefixed or symbolic strings for the mode option.","Validate the whole {...} block by parsing the file once after generation."],"exampleFix":"# before\nvardir = /opt/puppet { owner = puppet, mode = 0o644 }\n\n# after\nvardir = /opt/puppet { owner = puppet, mode = 0644 }","handlingStrategy":"validation","validationCode":"mode_value = '0644'\nraise ArgumentError, 'mode must be digits only' unless mode_value =~ /^\\d+$/","typeGuard":"numeric_mode = ->(v) { v.to_s.match?(/^\\d+$/) }","tryCatchPattern":"begin\n  Puppet::Settings::ConfigFile.parse_file(file, text, [])\nrescue ArgumentError => e\n  raise unless e.message.include?('File modes must be numbers')\n  Puppet.err(\"write modes as plain octal digits, e.g. mode = 0644\")\n  raise\nend","preventionTips":["Never emit 0o-prefixed or symbolic modes into config-file braces","Format modes with sprintf('%04o', mode_int) in generators","Prefer 4-digit octal (0644) to make intent explicit"],"tags":["puppet","settings","config-file","file-mode","permissions"],"backgroundTag":"invalid-file-mode","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}