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
- Clamp width/height to positive values and verify both DCs are live at call time (create dest with CreateCompatibleDC immediately before the blit)
- Re-acquire screen DCs (GetDC/ReleaseDC pairs) around each capture instead of caching them
- 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
- Acquire DCs (GetDC/CreateCompatibleDC) immediately before blitting and release right after
- Clamp width/height to positive values; recompute them after window resize events
- Do not reuse DCs across display-mode or DPI changes
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
- Create image list failed
- Invalid JSON passed to callback: ${e.message}. Message: ${in
- Callback '${callbackID}' not registered!!!
- Invalid JSON passed to Notify: ${notifyMessage}
- CancellablePromise does not support transparent subclassing.
AI-assisted analysis of wailsapp/wails@0e754b1b40 (2026-08-15).
Data as JSON: /api/errors/5130695140438024.
Report an issue: GitHub.