wailsapp/wails · error
Failed to create null brush
Error message
Failed to create null brush
What it means
NewNullBrush creates a BS_NULL brush via CreateBrushIndirect and panics if the handle is NULL. A null brush is used for transparent fill; the package-level variable nullBrush in canvas.go means this runs once at init. Failure of CreateBrushIndirect for BS_NULL is only expected under GDI handle exhaustion or during process teardown, so hitting this panic almost always means the process has leaked ~10000 GDI objects.
Source
Thrown at v2/internal/frontend/desktop/windows/winc/brush.go:55
}
return &Brush{hBrush, lb}
}
func NewHatchedColorBrush(color Color) *Brush {
lb := w32.LOGBRUSH{LbStyle: w32.BS_HATCHED, LbColor: w32.COLORREF(color)}
hBrush := w32.CreateBrushIndirect(&lb)
if hBrush == 0 {
panic("Faild to create solid color brush")
}
return &Brush{hBrush, lb}
}
func NewNullBrush() *Brush {
lb := w32.LOGBRUSH{LbStyle: w32.BS_NULL}
hBrush := w32.CreateBrushIndirect(&lb)
if hBrush == 0 {
panic("Failed to create null brush")
}
return &Brush{hBrush, lb}
}
func (br *Brush) GetHBRUSH() w32.HBRUSH {
return br.hBrush
}
func (br *Brush) GetLOGBRUSH() *w32.LOGBRUSH {
return &br.logBrush
}
func (br *Brush) Dispose() {
if br.hBrush != 0 {
w32.DeleteObject(w32.HGDIOBJ(br.hBrush))
br.hBrush = 0
}View on GitHub (pinned to 0e754b1b40)
Solutions
- Treat this as a symptom: profile GDI objects (Task Manager, GDIView) to find the real leak consuming handles
- Check for third-party DLLs/hooks injected into the process that allocate GDI handles at startup
- Ensure Pen/Brush/Font/Bitmap objects created via winc or direct w32 calls are all paired with DeleteObject/DeleteDC
Defensive patterns
Strategy: validation
Validate before calling
// NewNullBrush runs at package init (nullBrush var); you cannot pre-check it.
// Prevent instead: keep the GDI handle count low before importing heavy UI packages.
// Diagnostic check you can run at app start:
if h := w32.GetGuiResources(w32.GetCurrentProcess(), 0 /*GR_GDIOBJECTS*/); h > 9000 {
log.Printf("GDI handles at %d — leak before UI init", h)
} Prevention
- Treat this init-time panic as evidence of a pre-existing GDI leak in the process
- Audit all cgo/native dependencies that allocate GDI objects before your UI starts
When it happens
Trigger: GDI handle table full when NewNullBrush is first called (i.e. the leak happened before this package initialized); GDI already invalidated during shutdown-time use.
Common situations: Rarely seen because it fires at package init; when it does, another library or a cgo dependency has already consumed the GDI quota before winc's canvas package initialized.
Related errors
- Faild to create solid color brush
- Create canvas from %v failed.
- CreateFontIndirect failed
- GetSysColorBrush failed
- Cannot create canvas from invalid HDC.
AI-assisted analysis of wailsapp/wails@0e754b1b40 (2026-08-15).
Data as JSON: /api/errors/9e3049e42cbc1926.
Report an issue: GitHub.