puppetlabs/puppet · error · Puppet::Error

%{klass} could not read %{path}: %{detail}

Error message

%{klass} could not read %{path}: %{detail}

What it means

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: ...'.

Source

Thrown at lib/puppet/util/filetype.rb:52

    # Rename the read and write methods, so that we're sure they
    # maintain the stats.
    klass.class_eval do
      # Rename the read method
      define_method(:real_read, instance_method(:read))
      define_method(:read) do
        val = real_read
        @loaded = Time.now
        if val
          val.gsub(/# HEADER.*\n/, '')
        else
          ""
        end
      rescue Puppet::Error
        raise
      rescue => detail
        message = _("%{klass} could not read %{path}: %{detail}") % { klass: self.class, path: @path, detail: detail }
        Puppet.log_exception(detail, message)
        raise Puppet::Error, message, detail.backtrace
      end

      # And then the write method
      define_method(:real_write, instance_method(:write))
      define_method(:write) do |text|
        val = real_write(text)
        @synced = Time.now
        val
      rescue Puppet::Error
        raise
      rescue => detail
        message = _("%{klass} could not write %{path}: %{detail}") % { klass: self.class, path: @path, detail: detail }
        Puppet.log_exception(detail, message)
        raise Puppet::Error, message, detail.backtrace
      end
    end
  end

View on GitHub (pinned to e227c27540)

Solutions

  1. Check existence and permissions for the agent user (ls -l, sudo -u <agent> test -r) and fix ownership or ACLs
  2. Treat a missing file as empty data where the provider allows it (many FileParsing providers create the file lazily)
  3. Rescue Puppet::Error at the call site and report or degrade instead of crashing the run

Example fix

# before
content = Puppet::Util::FileType.filetype(:flat).new('/etc/app/keys').read
# => Puppet::Error: ... could not read /etc/app/keys: Permission denied

# after
path = '/etc/app/keys'
content = if File.readable?(path)
  Puppet::Util::FileType.filetype(:flat).new(path).read
else
  Puppet.warning "#{path} not readable; assuming empty"
  ''
end
Defensive patterns

Strategy: try-catch

Validate before calling

content = if File.exist?(path) && File.readable?(path)
  Puppet::Util::FileType.filetype(:flat).new(path).read
else
  ''
end

Try / catch

begin
  content = Puppet::Util::FileType.filetype(:flat).new(path).read
rescue Puppet::Error => e
  Puppet.err("cannot read #{path}: #{e.message}")
  content = ''
end

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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