{"record":{"id":"4adffd88bb439d48","repo":"puppetlabs/puppet","slug":"deviceiocontrol-handle-fsctl-get-reparse-point","errorCode":null,"errorMessage":"DeviceIoControl(#{handle}, FSCTL_GET_REPARSE_POINT) returned unknown tag 0x#{reparse_tag.to_s(16).upcase}","messagePattern":"DeviceIoControl\\(#(.+?), FSCTL_GET_REPARSE_POINT\\) returned unknown tag 0x#(.+?)","errorType":"exception","errorClass":"Puppet::Util::Windows::Error","httpStatus":null,"severity":"warning","filePath":"lib/puppet/util/windows/file.rb","lineNumber":156,"sourceCode":"                                        \"#{security_attributes}, #{creation_disposition.to_s(8)}, \" \\\n                                        \"#{flags_and_attributes.to_s(8)}, #{template_file_handle})\"\n  end\n\n  def self.get_reparse_point_data(handle, &block)\n    # must be multiple of 1024, min 10240\n    FFI::MemoryPointer.new(MAXIMUM_REPARSE_DATA_BUFFER_SIZE) do |reparse_data_buffer_ptr|\n      device_io_control(handle, FSCTL_GET_REPARSE_POINT, nil, reparse_data_buffer_ptr)\n\n      reparse_tag = reparse_data_buffer_ptr.read_win32_ulong\n      buffer_type = case reparse_tag\n                    when IO_REPARSE_TAG_SYMLINK\n                      SYMLINK_REPARSE_DATA_BUFFER\n                    when IO_REPARSE_TAG_MOUNT_POINT\n                      MOUNT_POINT_REPARSE_DATA_BUFFER\n                    when IO_REPARSE_TAG_NFS\n                      raise Puppet::Util::Windows::Error, \"Retrieving NFS reparse point data is unsupported\"\n                    else\n                      raise Puppet::Util::Windows::Error, \"DeviceIoControl(#{handle}, \" \\\n                                                          \"FSCTL_GET_REPARSE_POINT) returned unknown tag 0x#{reparse_tag.to_s(16).upcase}\"\n                    end\n\n      yield buffer_type.new(reparse_data_buffer_ptr)\n    end\n\n    # underlying struct MemoryPointer has been cleaned up by this point, nothing to return\n    nil\n  end\n\n  def self.get_reparse_point_tag(handle)\n    reparse_tag = nil\n\n    # must be multiple of 1024, min 10240\n    FFI::MemoryPointer.new(MAXIMUM_REPARSE_DATA_BUFFER_SIZE) do |reparse_data_buffer_ptr|\n      device_io_control(handle, FSCTL_GET_REPARSE_POINT, nil, reparse_data_buffer_ptr)\n\n      # DWORD ReparseTag is the first member of the struct","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/util/windows/file.rb#L138-L174","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Rescue Puppet::Util::Windows::Error, match /unknown tag/ in the message, and treat the file as non-symlink","Pre-check with get_reparse_point_tag and whitelist only SYMLINK (0xA000000C) and MOUNT_POINT (0xA0000003)","Exclude OneDrive/WindowsApps trees from link-following resources","Upgrade Puppet - newer releases recognize more reparse tags"],"exampleFix":"// before\nPuppet::Util::Windows::File.get_reparse_point_data(handle) { |buf| ... }  # cloud tag -> raise\n\n// after\nKNOWN = [Puppet::Util::Windows::File::IO_REPARSE_TAG_SYMLINK,\n         Puppet::Util::Windows::File::IO_REPARSE_TAG_MOUNT_POINT]\nif KNOWN.include?(Puppet::Util::Windows::File.get_reparse_point_tag(handle))\n  Puppet::Util::Windows::File.get_reparse_point_data(handle) { |buf| ... }\nend","handlingStrategy":"validation","validationCode":"KNOWN_TAGS = [Puppet::Util::Windows::File::IO_REPARSE_TAG_SYMLINK,\n              Puppet::Util::Windows::File::IO_REPARSE_TAG_MOUNT_POINT].freeze\ntag = Puppet::Util::Windows::File.get_reparse_point_tag(handle)\nonly_known = KNOWN_TAGS.include?(tag)\nPuppet::Util::Windows::File.get_reparse_point_data(handle) { |b| ... } if only_known","typeGuard":"def readable_reparse_tag?(tag)\n  [Puppet::Util::Windows::File::IO_REPARSE_TAG_SYMLINK,\n   Puppet::Util::Windows::File::IO_REPARSE_TAG_MOUNT_POINT].include?(tag)\nend","tryCatchPattern":"begin\n  Puppet::Util::Windows::File.get_reparse_point_data(handle) { |buf| process(buf) }\nrescue Puppet::Util::Windows::Error => e\n  raise unless e.message =~ /unknown tag/\n  # cloud placeholder / filter-driver tag - not a symlink; treat as regular file\nend","preventionTips":["Whitelist tags instead of blacklisting unknown ones","Exclude OneDrive-synced profile folders and WindowsApps from reparse inspection","Upgrade Puppet when new Windows reparse tags appear in your fleet"],"tags":["windows","reparse-point","symlink","onedrive","ffi","puppet"],"backgroundTag":"unknown-reparse-point-tag","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}