puppetlabs/puppet · error · Puppet::Util::Windows::Error

Failed to set file attributes

Error message

Failed to set file attributes

What it means

Puppet::Util::Windows::File.set_attributes calls SetFileAttributesW and raises Puppet::Util::Windows::Error when it returns FALSE. It is used by add_attributes/remove_attributes (e.g. toggling FILE_ATTRIBUTE_READONLY around file operations). The appended Win32 message and e.code give the cause: invalid path, access denied, or the file being locked in an incompatible state.

Source

Thrown at lib/puppet/util/windows/file.rb:120

    if (oldattrs | flags) != oldattrs
      set_attributes(path, oldattrs | flags)
    end
  end
  module_function :add_attributes

  def remove_attributes(path, flags)
    oldattrs = get_attributes(path)

    if (oldattrs & ~flags) != oldattrs
      set_attributes(path, oldattrs & ~flags)
    end
  end
  module_function :remove_attributes

  def set_attributes(path, flags)
    success = SetFileAttributesW(wide_string(path), flags) != FFI::WIN32_FALSE
    raise Puppet::Util::Windows::Error, _("Failed to set file attributes") unless success

    success
  end
  module_function :set_attributes

  # define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
  INVALID_HANDLE_VALUE = FFI::Pointer.new(-1).address
  def self.create_file(file_name, desired_access, share_mode, security_attributes,
                       creation_disposition, flags_and_attributes, template_file_handle)

    result = CreateFileW(wide_string(file_name.to_s),
                         desired_access, share_mode, security_attributes, creation_disposition,
                         flags_and_attributes, template_file_handle)

    return result unless result == INVALID_HANDLE_VALUE

    raise Puppet::Util::Windows::Error, "CreateFile(#{file_name}, #{desired_access.to_s(8)}, #{share_mode.to_s(8)}, " \
                                        "#{security_attributes}, #{creation_disposition.to_s(8)}, " \

View on GitHub (pinned to e227c27540)

Solutions

  1. Confirm the file still exists at the moment of the call (get_attributes(path, false))
  2. Map e.code: 5 = elevate or fix ACLs, 32 = retry after the lock clears, 2/3 = fix the path
  3. Sequence operations so attributes are changed immediately before the dependent action, minimizing the race window
  4. Schedule AV exclusions for managed directories if code 32 recurs

Example fix

// before
Puppet::Util::Windows::File.set_attributes(path, new_flags)

// after
begin
  Puppet::Util::Windows::File.set_attributes(path, new_flags)
rescue Puppet::Util::Windows::Error => e
  retry if e.code == 32 && (retry_count += 1) < 3
  raise
end
Defensive patterns

Strategy: try-catch

Validate before calling

exists = Puppet::Util::Windows::File.get_attributes(path, false) != Puppet::Util::Windows::File::INVALID_FILE_ATTRIBUTES
raise ArgumentError, "#{path} gone" unless exists

Try / catch

begin
  Puppet::Util::Windows::File.set_attributes(path, flags)
rescue Puppet::Util::Windows::Error => e
  retry if e.code == 32 && (tries ||= 0) < 3  # sharing violation is transient
  raise
end

Prevention

When it happens

Trigger: set_attributes(path, flags) when the path no longer exists (2/3), the caller cannot write the file's metadata (5), or another handle has the file open with sharing restrictions (32). Also triggered by passing a combined flags value where some bits conflict with the file's current state.

Common situations: Puppet clearing the read-only bit before deleting or replacing a file while antivirus or a backup job holds it; files on read-only network shares; non-admin agents touching system files; files already deleted by a previous resource in the same run.

Related errors


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