wailsapp/wails · error
GetClientRect(%d) failed
Error message
GetClientRect(%d) failed
What it means
GetClientRect returned FALSE, so the wrapper panics. The Win32 API fails when the given HWND is not a valid window — destroyed, not yet fully created, belongs to another process, or is a garbage handle. The panic message includes the numeric HWND to identify which handle failed.
Source
Thrown at v3/pkg/w32/user32.go:766
}
func InvalidateRect(hwnd HWND, rect *RECT, erase bool) bool {
ret, _, _ := procInvalidateRect.Call(
uintptr(hwnd),
uintptr(unsafe.Pointer(rect)),
uintptr(BoolToBOOL(erase)))
return ret != 0
}
func GetClientRect(hwnd HWND) *RECT {
var rect RECT
ret, _, _ := procGetClientRect.Call(
uintptr(hwnd),
uintptr(unsafe.Pointer(&rect)))
if ret == 0 {
panic(fmt.Sprintf("GetClientRect(%d) failed", hwnd))
}
return &rect
}
func GetDC(hwnd HWND) HDC {
ret, _, _ := procGetDC.Call(
uintptr(hwnd))
return HDC(ret)
}
func ReleaseDC(hwnd HWND, hDC HDC) bool {
ret, _, _ := procReleaseDC.Call(
uintptr(hwnd),
uintptr(hDC))
return ret != 0View on GitHub (pinned to 0e754b1b40)
Solutions
- Guard the call with w32.IsWindow(hwnd) (or check hwnd != 0) before measuring
- Stop layout/resize goroutines when the window-destroyed event arrives, before the HWND becomes invalid
- Re-fetch HWNDs from the live window object instead of caching them across lifecycle events
- Recover in UI helpers so a shutdown race degrades to a skipped layout pass
Example fix
// before
rect := w32.GetClientRect(hwnd) // panics during teardown
// after
if hwnd == 0 || !w32.IsWindow(hwnd) {
return // window destroyed; skip measurement
}
rect := w32.GetClientRect(hwnd) Defensive patterns
Strategy: validation
Validate before calling
if hwnd == 0 || !w32.IsWindow(hwnd) {
return nil, errors.New("GetClientRect: invalid window handle")
}
rect := w32.GetClientRect(hwnd) Try / catch
defer func() {
if r := recover(); r != nil {
rect = nil // window died mid-measurement; skip this pass
}
}() Prevention
- Stop measurement goroutines on window-destroy events
- Never cache HWNDs across window recreation
- Check IsWindow before any HWND-taking call during shutdown paths
When it happens
Trigger: Calling GetClientRect on a window after WM_DESTROY/CloseHandle; using an HWND captured before window creation completed; passing 0 or an HWND from a different thread's window during teardown; calling after the native window was destroyed because the browser process crashed.
Common situations: Wails v3 Windows window-events code reading the client rect during shutdown or in a resize callback racing destruction; retry/recreate-window logic that keeps stale HWNDs; dialogs whose owner window was closed by the user.
Related errors
- ${await response.text()}
- invalid stream batch acknowledgement
- no element matches selector: ' + target.selector
- no focused element to type into; pass a selector or click a
- SendMessage(LVM_SETCALLBACKMASK)
AI-assisted analysis of wailsapp/wails@0e754b1b40 (2026-08-15).
Data as JSON: /api/errors/c69835eb5d9f5274.
Report an issue: GitHub.