{"record":{"id":"5130695140438024","repo":"wailsapp/wails","slug":"bitblt-failed","errorCode":null,"errorMessage":"BitBlt failed","messagePattern":"BitBlt failed","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/pkg/w32/gdi32.go","lineNumber":114,"sourceCode":"\t\tuintptr(hdc))\n\n\treturn int(ret)\n}\n\nfunc BitBlt(hdcDest HDC, nXDest, nYDest, nWidth, nHeight int, hdcSrc HDC, nXSrc, nYSrc int, dwRop uint) {\n\tret, _, _ := procBitBlt.Call(\n\t\tuintptr(hdcDest),\n\t\tuintptr(nXDest),\n\t\tuintptr(nYDest),\n\t\tuintptr(nWidth),\n\t\tuintptr(nHeight),\n\t\tuintptr(hdcSrc),\n\t\tuintptr(nXSrc),\n\t\tuintptr(nYSrc),\n\t\tuintptr(dwRop))\n\n\tif ret == 0 {\n\t\tpanic(\"BitBlt failed\")\n\t}\n}\n\nfunc PatBlt(hdc HDC, nXLeft, nYLeft, nWidth, nHeight int, dwRop uint) {\n\tret, _, _ := procPatBlt.Call(\n\t\tuintptr(hdc),\n\t\tuintptr(nXLeft),\n\t\tuintptr(nYLeft),\n\t\tuintptr(nWidth),\n\t\tuintptr(nHeight),\n\t\tuintptr(dwRop))\n\n\tif ret == 0 {\n\t\tpanic(\"PatBlt failed\")\n\t}\n}\n\nfunc CloseEnhMetaFile(hdc HDC) HENHMETAFILE {","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/wailsapp/wails/blob/0e754b1b40ba9044c2a1460e23b7c3de20fc5cf3/v3/pkg/w32/gdi32.go#L96-L132","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nw32.BitBlt(dst, 0, 0, w, h, src, x, y, w32.SRCCOPY) // panics if w or h <= 0\n\n// after\nif w > 0 && h > 0 {\n\tw32.BitBlt(dst, 0, 0, w, h, src, x, y, w32.SRCCOPY)\n}","handlingStrategy":"validation","validationCode":"func safeBitBlt(dst, src w32.HDC, x, y, w, h int) bool {\n\tif w <= 0 || h <= 0 || dst == 0 || src == 0 {\n\t\treturn false\n\t}\n\tw32.BitBlt(dst, x, y, w, h, src, 0, 0, w32.SRCCOPY)\n\treturn true\n}","typeGuard":null,"tryCatchPattern":"defer func() {\n\tif r := recover(); r != nil {\n\t\tlog.Printf(\"BitBlt failed: %v\", r)\n\t}\n}()\nw32.BitBlt(dst, 0, 0, w, h, src, x, y, w32.SRCCOPY)","preventionTips":["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"],"tags":["windows","win32","gdi","bitblt","panic","native","screenshot"],"backgroundTag":null,"analyzedSha":"0e754b1b40ba9044c2a1460e23b7c3de20fc5cf3","analyzedAt":"2026-08-15T14:17:36.034Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}