wailsapp/wails · error

Invoke DragQueryFile error.

Error message

Invoke DragQueryFile error.

What it means

The DragQueryFile wrapper panicked because the second call (the one that copies the file name for a specific index) returned 0, meaning the call failed — most often the buffer was too small, iFile was out of range, or hDrop was invalid. The code sizes the buffer from the first DragQueryFile(0xFFFFFFFF) call, which returns the FILE COUNT, not the longest path length, so deep paths overflow the buffer and make the copy fail.

Source

Thrown at v3/pkg/w32/shell32.go:284

	ret, _, _ := procDragQueryFile.Call(
		hDrop,
		uintptr(iFile),
		0,
		0)

	fileCount = uint(ret)

	if iFile != 0xFFFFFFFF {
		buf := make([]uint16, fileCount+1)

		ret, _, _ := procDragQueryFile.Call(
			hDrop,
			uintptr(iFile),
			uintptr(unsafe.Pointer(&buf[0])),
			uintptr(fileCount+1))

		if ret == 0 {
			panic("Invoke DragQueryFile error.")
		}

		fileName = syscall.UTF16ToString(buf)
	}

	return
}

func DragQueryPoint(hDrop HDROP) (x, y int, isClientArea bool) {
	var pt POINT
	ret, _, _ := procDragQueryPoint.Call(
		uintptr(hDrop),
		uintptr(unsafe.Pointer(&pt)))

	return int(pt.X), int(pt.Y), (ret == 1)
}

func DragFinish(hDrop HDROP) {

View on GitHub (pinned to 0e754b1b40)

Solutions

  1. Fix the wrapper: size the buffer by calling DragQueryFile(hDrop, iFile, nil, 0) first — it returns the required character count — then allocate count+1
  2. Validate iFile < fileCount before the copy call
  3. Do not call DragFinish until all DragQueryFile/QueryPoint reads are done
  4. Recover around the drop-handling loop so one bad entry does not crash the app

Example fix

// before
ret, _, _ := procDragQueryFile.Call(hDrop, uintptr(0xFFFFFFFF), 0, 0)
fileCount = uint(ret)
buf := make([]uint16, fileCount+1) // WRONG: sizes by file count

// after
// pass iFile with null buffer to get needed length
lenRet, _, _ := procDragQueryFile.Call(hDrop, uintptr(iFile), 0, 0)
buf := make([]uint16, lenRet+1)
ret, _, _ := procDragQueryFile.Call(hDrop, uintptr(iFile),
    uintptr(unsafe.Pointer(&buf[0])), uintptr(lenRet+1))
if ret == 0 { panic("Invoke DragQueryFile error.") }
Defensive patterns

Strategy: validation

Validate before calling

// fixed wrapper: query required length first
l, _, _ := procDragQueryFile.Call(hDrop, uintptr(iFile), 0, 0)
if l == 0 { return } // invalid index or handle
buf := make([]uint16, l+1)

Try / catch

defer func() {
    if r := recover(); r != nil {
        log.Printf("DragQueryFile failed for index %d: %v", iFile, r)
    }
}()

Prevention

When it happens

Trigger: Dropping files whose full path is longer than the number of dropped files (almost always true in practice — e.g. one file with a 120-char path gets a 2-uint16 buffer); calling with iFile >= the count returned by the enumeration pass; using hDrop after DragFinish.

Common situations: Wails drag-and-drop handlers on Windows processing files from long directory trees or with long Unicode names; re-reading the drop handle after it was finished; races where the drop list is queried twice.

Related errors


AI-assisted analysis of wailsapp/wails@0e754b1b40 (2026-08-15). Data as JSON: /api/errors/08d6d68420e155f2. Report an issue: GitHub.