puppetlabs/puppet · error · Puppet::Error

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

Error message

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

What it means

The write twin of FileType's read decorator: exceptions from the filetype-specific write that are not already Puppet::Error (permission denied, read-only filesystem, ENOSPC) are logged and re-raised as Puppet::Error '%{klass} could not write %{path}: %{detail}'. The cache is only marked synced (@synced = Time.now) when the write succeeds.

Source

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

        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

  def self.filetype(type)
    @filetypes[type]
  end

  # Pick or create a filebucket to use.
  def bucket
    @bucket ||= Puppet::Type.type(:filebucket).mkdefaultbucket.bucket
  end

  def initialize(path, default_mode = nil)
    raise ArgumentError, _("Path is nil") if path.nil?

    @path = path
    @default_mode = default_mode

View on GitHub (pinned to e227c27540)

Solutions

  1. Verify write permission and filesystem mutability for the agent user (ls -l, lsattr)
  2. Ensure the parent directory exists and the file is not immutable
  3. Rescue Puppet::Error at the call site, report it, and remediate (permissions/mount) before retrying

Example fix

# before
Puppet::Util::FileType.filetype(:flat).new('/etc/motd').write(text)
# => Puppet::Error: ... could not write /etc/motd: Read-only file system

# after
begin
  Puppet::Util::FileType.filetype(:flat).new('/etc/motd').write(text)
rescue Puppet::Error => e
  Puppet.err("motd not updated: #{e.message}")
end
Defensive patterns

Strategy: try-catch

Validate before calling

writable = File.exist?(path) ? File.writable?(path) : File.writable?(File.dirname(path))
raise ArgumentError, "#{path} not writable" unless writable
ft.write(text)

Try / catch

begin
  ft.write(text)
rescue Puppet::Error => e
  Puppet.err("write failed: #{e.message}")
  raise unless e.message =~ /Resource temporarily unavailable/
end

Prevention

When it happens

Trigger: Puppet::Util::FileType.filetype(:flat).new('/etc/app.conf').write(text) as a user without write permission, on a read-only mount, or when the target's parent directory is missing; crontab writes failing through the cron binary hit the same wrapper.

Common situations: Agents running least-privilege but managing root-owned files, immutable/append-only files (chattr +i), containers with read-only /etc, and full disks.

Related errors


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