{"record":{"id":"fccbd967756b5338","repo":"puppetlabs/puppet","slug":"out-buffer-is-required","errorCode":null,"errorMessage":"out_buffer is required","messagePattern":"out_buffer is required","errorType":"validation","errorClass":"Puppet::Util::Windows::Error","httpStatus":null,"severity":"error","filePath":"lib/puppet/util/windows/file.rb","lineNumber":183,"sourceCode":"  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\n      reparse_tag = reparse_data_buffer_ptr.read_win32_ulong\n    end\n\n    reparse_tag\n  end\n\n  def self.device_io_control(handle, io_control_code, in_buffer = nil, out_buffer = nil)\n    if out_buffer.nil?\n      raise Puppet::Util::Windows::Error, _(\"out_buffer is required\")\n    end\n\n    FFI::MemoryPointer.new(:dword, 1) do |bytes_returned_ptr|\n      result = DeviceIoControl(\n        handle,\n        io_control_code,\n        in_buffer, in_buffer.nil? ? 0 : in_buffer.size,\n        out_buffer, out_buffer.size,\n        bytes_returned_ptr,\n        nil\n      )\n\n      if result == FFI::WIN32_FALSE\n        raise Puppet::Util::Windows::Error, \"DeviceIoControl(#{handle}, #{io_control_code}, \" \\\n                                            \"#{in_buffer}, #{in_buffer ? in_buffer.size : ''}, \" \\\n                                            \"#{out_buffer}, #{out_buffer ? out_buffer.size : ''}\"\n      end\n    end","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/util/windows/file.rb#L165-L201","documentation":"Puppet::Util::Windows::File.device_io_control raises Puppet::Util::Windows::Error('out_buffer is required') when called with out_buffer nil - DeviceIoControl always needs a destination for returned bytes, so this is a programmer error at the call site, not a system failure. No Win32 call has been made yet when it raises.","triggerScenarios":"Calling device_io_control(handle, code, in_buffer) with only three arguments (out_buffer defaults to nil), or explicitly passing nil while intending an in-place buffer. Typical when adapting sample code for codes that only write output (e.g. FSCTL_GET_REPARSE_POINT).","commonSituations":"First-time FFI wrappers around DeviceIoControl assuming output is optional; refactors that dropped the fourth argument; copy-paste from in-buffer-only IOCTL examples.","solutions":["Always pass an out_buffer, e.g. FFI::MemoryPointer.new(MAXIMUM_REPARSE_DATA_BUFFER_SIZE) (>= 10240 bytes for reparse data)","Read returned byte counts from the API result/overlapped struct rather than inferring from buffer size","Treat this raise as a defect signal in your own wrapper - fix the call, do not rescue it"],"exampleFix":"// before\nPuppet::Util::Windows::File.device_io_control(handle, FSCTL_GET_REPARSE_POINT, nil)  # nil out_buffer\n\n// after\nFFI::MemoryPointer.new(10240) do |out|\n  Puppet::Util::Windows::File.device_io_control(handle, FSCTL_GET_REPARSE_POINT, nil, out)\nend","handlingStrategy":"validation","validationCode":"raise ArgumentError, 'device_io_control requires out_buffer' if out_buffer.nil?\nout_buffer ||= FFI::MemoryPointer.new(Puppet::Util::Windows::File::MAXIMUM_REPARSE_DATA_BUFFER_SIZE)","typeGuard":null,"tryCatchPattern":"begin\n  Puppet::Util::Windows::File.device_io_control(handle, code, in_buffer, out_buffer)\nrescue Puppet::Util::Windows::Error => e\n  raise unless e.message.include?('out_buffer is required')\n  raise ArgumentError, 'fix call site: out_buffer is mandatory'\nend","preventionTips":["Always allocate an output buffer; for reparse data it must be >= 10240 bytes","Treat this raise as a bug in the caller - never swallow it","Wrap device_io_control once in your own helper that enforces the buffer contract"],"tags":["windows","ffi","deviceiocontrol","argumenterror","programmer-error","puppet"],"backgroundTag":"missing-required-parameter","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}