wailsapp/wails · error

BitBlt failed

Error message

BitBlt failed

What it means

BitBlt is a wrapper over the GDI BitBlt function in Wails' internal w32 package; it panics when the native stretch/transfer returns FALSE. BitBlt fails when the two HDCs are incompatible (e.g. source is a screen DC with CAPTUREBLT while destination constraints differ), coordinates/extent are invalid (zero or negative width/height), the DC handles are stale/deleted, or a driver-level error occurs. Like ImageList_Create, it currently has no callers in v3 (it is inherited from v2's winc canvas code), so only direct users of v3/pkg/w32 can trigger it.

Source

Thrown at v3/pkg/w32/gdi32.go:114

		uintptr(hdc))

	return int(ret)
}

func BitBlt(hdcDest HDC, nXDest, nYDest, nWidth, nHeight int, hdcSrc HDC, nXSrc, nYSrc int, dwRop uint) {
	ret, _, _ := procBitBlt.Call(
		uintptr(hdcDest),
		uintptr(nXDest),
		uintptr(nYDest),
		uintptr(nWidth),
		uintptr(nHeight),
		uintptr(hdcSrc),
		uintptr(nXSrc),
		uintptr(nYSrc),
		uintptr(dwRop))

	if ret == 0 {
		panic("BitBlt failed")
	}
}

func PatBlt(hdc HDC, nXLeft, nYLeft, nWidth, nHeight int, dwRop uint) {
	ret, _, _ := procPatBlt.Call(
		uintptr(hdc),
		uintptr(nXLeft),
		uintptr(nYLeft),
		uintptr(nWidth),
		uintptr(nHeight),
		uintptr(dwRop))

	if ret == 0 {
		panic("PatBlt failed")
	}
}

func CloseEnhMetaFile(hdc HDC) HENHMETAFILE {

View on GitHub (pinned to 0e754b1b40)

Solutions

  1. Clamp width/height to positive values and verify both DCs are live at call time (create dest with CreateCompatibleDC immediately before the blit)
  2. Re-acquire screen DCs (GetDC/ReleaseDC pairs) around each capture instead of caching them
  3. Replace the panicking wrapper at your call site with a direct procBitBlt call that returns an error, so failures are handleable

Example fix

// before
w32.BitBlt(dst, 0, 0, w, h, src, x, y, w32.SRCCOPY) // panics if w or h <= 0

// after
if w > 0 && h > 0 {
	w32.BitBlt(dst, 0, 0, w, h, src, x, y, w32.SRCCOPY)
}
Defensive patterns

Strategy: validation

Validate before calling

func safeBitBlt(dst, src w32.HDC, x, y, w, h int) bool {
	if w <= 0 || h <= 0 || dst == 0 || src == 0 {
		return false
	}
	w32.BitBlt(dst, x, y, w, h, src, 0, 0, w32.SRCCOPY)
	return true
}

Try / catch

defer func() {
	if r := recover(); r != nil {
		log.Printf("BitBlt failed: %v", r)
	}
}()
w32.BitBlt(dst, 0, 0, w, h, src, x, y, w32.SRCCOPY)

Prevention

When it happens

Trigger: Calling w32.BitBlt with nWidth or nHeight <= 0, with an hdcSrc or hdcDest that has been released (DeleteDC'd), with mismatched DC origins for raster ops that require them, or during display-mode changes / locked desktops where GDI operations fail.

Common situations: Screen-capture or custom-drawing code ported from v2's winc canvas; using a DC after a resize or display change invalidated it; multi-monitor DPI transitions mid-blit.

Related errors


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