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

DeviceIoControl(#{handle}, FSCTL_GET_REPARSE_POINT) returned

Error message

DeviceIoControl(#{handle}, FSCTL_GET_REPARSE_POINT) returned unknown tag 0x#{reparse_tag.to_s(16).upcase}

What it means

In get_reparse_point_data, a reparse tag that is neither IO_REPARSE_TAG_SYMLINK, IO_REPARSE_TAG_MOUNT_POINT, nor IO_REPARSE_TAG_NFS raises this error, embedding the unknown tag in uppercase hex. Windows uses reparse points for far more than symlinks - cloud placeholders (OneDrive), AppExec links, dedup - and Puppet cannot map those tags to a buffer struct it knows how to read.

Source

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

                                        "#{security_attributes}, #{creation_disposition.to_s(8)}, " \
                                        "#{flags_and_attributes.to_s(8)}, #{template_file_handle})"
  end

  def self.get_reparse_point_data(handle, &block)
    # must be multiple of 1024, min 10240
    FFI::MemoryPointer.new(MAXIMUM_REPARSE_DATA_BUFFER_SIZE) do |reparse_data_buffer_ptr|
      device_io_control(handle, FSCTL_GET_REPARSE_POINT, nil, reparse_data_buffer_ptr)

      reparse_tag = reparse_data_buffer_ptr.read_win32_ulong
      buffer_type = case reparse_tag
                    when IO_REPARSE_TAG_SYMLINK
                      SYMLINK_REPARSE_DATA_BUFFER
                    when IO_REPARSE_TAG_MOUNT_POINT
                      MOUNT_POINT_REPARSE_DATA_BUFFER
                    when IO_REPARSE_TAG_NFS
                      raise Puppet::Util::Windows::Error, "Retrieving NFS reparse point data is unsupported"
                    else
                      raise Puppet::Util::Windows::Error, "DeviceIoControl(#{handle}, " \
                                                          "FSCTL_GET_REPARSE_POINT) returned unknown tag 0x#{reparse_tag.to_s(16).upcase}"
                    end

      yield buffer_type.new(reparse_data_buffer_ptr)
    end

    # underlying struct MemoryPointer has been cleaned up by this point, nothing to return
    nil
  end

  def self.get_reparse_point_tag(handle)
    reparse_tag = nil

    # must be multiple of 1024, min 10240
    FFI::MemoryPointer.new(MAXIMUM_REPARSE_DATA_BUFFER_SIZE) do |reparse_data_buffer_ptr|
      device_io_control(handle, FSCTL_GET_REPARSE_POINT, nil, reparse_data_buffer_ptr)

      # DWORD ReparseTag is the first member of the struct

View on GitHub (pinned to e227c27540)

Solutions

  1. Rescue Puppet::Util::Windows::Error, match /unknown tag/ in the message, and treat the file as non-symlink
  2. Pre-check with get_reparse_point_tag and whitelist only SYMLINK (0xA000000C) and MOUNT_POINT (0xA0000003)
  3. Exclude OneDrive/WindowsApps trees from link-following resources
  4. Upgrade Puppet - newer releases recognize more reparse tags

Example fix

// before
Puppet::Util::Windows::File.get_reparse_point_data(handle) { |buf| ... }  # cloud tag -> raise

// after
KNOWN = [Puppet::Util::Windows::File::IO_REPARSE_TAG_SYMLINK,
         Puppet::Util::Windows::File::IO_REPARSE_TAG_MOUNT_POINT]
if KNOWN.include?(Puppet::Util::Windows::File.get_reparse_point_tag(handle))
  Puppet::Util::Windows::File.get_reparse_point_data(handle) { |buf| ... }
end
Defensive patterns

Strategy: validation

Validate before calling

KNOWN_TAGS = [Puppet::Util::Windows::File::IO_REPARSE_TAG_SYMLINK,
              Puppet::Util::Windows::File::IO_REPARSE_TAG_MOUNT_POINT].freeze
tag = Puppet::Util::Windows::File.get_reparse_point_tag(handle)
only_known = KNOWN_TAGS.include?(tag)
Puppet::Util::Windows::File.get_reparse_point_data(handle) { |b| ... } if only_known

Type guard

def readable_reparse_tag?(tag)
  [Puppet::Util::Windows::File::IO_REPARSE_TAG_SYMLINK,
   Puppet::Util::Windows::File::IO_REPARSE_TAG_MOUNT_POINT].include?(tag)
end

Try / catch

begin
  Puppet::Util::Windows::File.get_reparse_point_data(handle) { |buf| process(buf) }
rescue Puppet::Util::Windows::Error => e
  raise unless e.message =~ /unknown tag/
  # cloud placeholder / filter-driver tag - not a symlink; treat as regular file
end

Prevention

When it happens

Trigger: Calling get_reparse_point_data on files carrying exotic reparse tags: OneDrive/cloud-files placeholders (IO_REPARSE_TAG_CLOUD*, 0x9000001c/0x9000001d family), MSIX/AppExecLink reparse points, Data Deduplication files, or third-party filter-driver tags.

Common situations: Puppet managing resources under OneDrive-synced user profiles (Desktop, Documents); inspecting files under C:\Program Files\WindowsApps; dedup-enabled volumes; newer Windows builds introducing tags this Puppet version predates.

Related errors


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