{"record":{"id":"e3535d8e5bb7f4c2","repo":"puppetlabs/puppet","slug":"klass-could-not-read-path-detail","errorCode":null,"errorMessage":"%{klass} could not read %{path}: %{detail}","messagePattern":"%(.+?) could not read %(.+?): %(.+?)","errorType":"exception","errorClass":"Puppet::Error","httpStatus":null,"severity":"error","filePath":"lib/puppet/util/filetype.rb","lineNumber":52,"sourceCode":"    # Rename the read and write methods, so that we're sure they\n    # maintain the stats.\n    klass.class_eval do\n      # Rename the read method\n      define_method(:real_read, instance_method(:read))\n      define_method(:read) do\n        val = real_read\n        @loaded = Time.now\n        if val\n          val.gsub(/# HEADER.*\\n/, '')\n        else\n          \"\"\n        end\n      rescue Puppet::Error\n        raise\n      rescue => detail\n        message = _(\"%{klass} could not read %{path}: %{detail}\") % { klass: self.class, path: @path, detail: detail }\n        Puppet.log_exception(detail, message)\n        raise Puppet::Error, message, detail.backtrace\n      end\n\n      # And then the write method\n      define_method(:real_write, instance_method(:write))\n      define_method(:write) do |text|\n        val = real_write(text)\n        @synced = Time.now\n        val\n      rescue Puppet::Error\n        raise\n      rescue => detail\n        message = _(\"%{klass} could not write %{path}: %{detail}\") % { klass: self.class, path: @path, detail: detail }\n        Puppet.log_exception(detail, message)\n        raise Puppet::Error, message, detail.backtrace\n      end\n    end\n  end\n","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/util/filetype.rb#L34-L70","documentation":"Puppet::Util::FileType wraps each concrete filetype (flat file, cron, ram) and decorates read/write with caching and error context. Any exception from the underlying read that is not already a Puppet::Error (typically Errno::ENOENT or Errno::EACCES from File.read) is logged and re-raised as Puppet::Error with the filetype class and path — e.g. 'Puppet::Util::FileType::FileFlat could not read /etc/hosts: ...'.","triggerScenarios":"Puppet::Util::FileType.filetype(:flat).new('/etc/app.conf').read when the file is missing, unreadable by the agent user, or is a directory; also via providers that use FileType for crontab-style targets.","commonSituations":"First run on a host where the managed file does not exist yet, root-owned files read by a non-root agent, SELinux denials, and flaky NFS mounts.","solutions":["Check existence and permissions for the agent user (ls -l, sudo -u <agent> test -r) and fix ownership or ACLs","Treat a missing file as empty data where the provider allows it (many FileParsing providers create the file lazily)","Rescue Puppet::Error at the call site and report or degrade instead of crashing the run"],"exampleFix":"# before\ncontent = Puppet::Util::FileType.filetype(:flat).new('/etc/app/keys').read\n# => Puppet::Error: ... could not read /etc/app/keys: Permission denied\n\n# after\npath = '/etc/app/keys'\ncontent = if File.readable?(path)\n  Puppet::Util::FileType.filetype(:flat).new(path).read\nelse\n  Puppet.warning \"#{path} not readable; assuming empty\"\n  ''\nend","handlingStrategy":"try-catch","validationCode":"content = if File.exist?(path) && File.readable?(path)\n  Puppet::Util::FileType.filetype(:flat).new(path).read\nelse\n  ''\nend","typeGuard":null,"tryCatchPattern":"begin\n  content = Puppet::Util::FileType.filetype(:flat).new(path).read\nrescue Puppet::Error => e\n  Puppet.err(\"cannot read #{path}: #{e.message}\")\n  content = ''\nend","preventionTips":["Pre-check File.readable? for the agent's user before reading managed files","Rescue Puppet::Error around FileType reads; the wrapper already logged the cause","Ship files with correct ownership and SELinux contexts"],"tags":["puppet","file-io","permissions","filetype"],"backgroundTag":"file-read-failed","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}