{"record":{"id":"12c322ebec785c00","repo":"wailsapp/wails","slug":"failed-to-load-gdi32-dll-v","errorCode":null,"errorMessage":"failed to load gdi32.dll: %v","messagePattern":"failed to load gdi32\\.dll: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"v2/internal/frontend/desktop/windows/winc/icon.go","lineNumber":40,"sourceCode":"var (\n\tuser32                 = syscall.NewLazyDLL(\"user32.dll\")\n\tgdi32                  = syscall.NewLazyDLL(\"gdi32.dll\")\n\tprocGetIconInfo        = user32.NewProc(\"GetIconInfo\")\n\tprocDeleteObject       = gdi32.NewProc(\"DeleteObject\")\n\tprocGetObject          = gdi32.NewProc(\"GetObjectW\")\n\tprocGetDIBits          = gdi32.NewProc(\"GetDIBits\")\n\tprocCreateCompatibleDC = gdi32.NewProc(\"CreateCompatibleDC\")\n\tprocSelectObject       = gdi32.NewProc(\"SelectObject\")\n\tprocDeleteDC           = gdi32.NewProc(\"DeleteDC\")\n)\n\nfunc init() {\n\t// Validate DLL loads at initialization time to surface missing APIs early\n\tif err := user32.Load(); err != nil {\n\t\tpanic(fmt.Sprintf(\"failed to load user32.dll: %v\", err))\n\t}\n\tif err := gdi32.Load(); err != nil {\n\t\tpanic(fmt.Sprintf(\"failed to load gdi32.dll: %v\", err))\n\t}\n}\n\n// ICONINFO mirrors the Win32 ICONINFO struct\ntype ICONINFO struct {\n\tFIcon    int32\n\tXHotspot uint32\n\tYHotspot uint32\n\tHbmMask  uintptr\n\tHbmColor uintptr\n}\n\n// http://msdn.microsoft.com/en-us/library/windows/desktop/dd183376.aspx\ntype BITMAPINFOHEADER struct {\n\tBiSize          uint32\n\tBiWidth         int32\n\tBiHeight        int32\n\tBiPlanes        uint16","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/wailsapp/wails/blob/0e754b1b40ba9044c2a1460e23b7c3de20fc5cf3/v2/internal/frontend/desktop/windows/winc/icon.go#L22-L58","documentation":"The same icon.go init that loads user32.dll also loads gdi32.dll and panics with the wrapped error if it fails. gdi32.dll is a permanent system DLL used for all drawing (icon bitmaps, DCs, brushes), so a load failure is environmental, not a code bug: blocked by security software, missing in stripped-down Windows containers/server-core-without-GUI, or an emulation layer without a matching-bitness gdi32.","triggerScenarios":"Importing the winc icon package (any transitively importing package triggers init) on headless Windows containers; 64-bit process under emulation with only 32-bit gdi32; DLL load blocked by AppLocker/EDR; corrupted system DLL search path.","commonSituations":"Docker 'windows' container images based on servercore:nanoserver missing GUI DLLs when a GUI dependency sneaks into a service build; CI agents without interactive desktops when tests import winc.","solutions":["Keep GUI dependencies (winc imports) out of headless services/containers — split them behind a build tag or separate package so init never runs there","Read the wrapped %v error: access-denied -> policy/AV; module-not-found -> missing DLL on that SKU","On stripped SKUs, switch to a full desktop or servercore image that includes gdi32.dll","Verify with `dumpbin /dependents` (or Dependency Walker) that the exe's DLL expectations match the host"],"exampleFix":"// before: headless service transitively imports winc -> init panics without gdi32\nimport _ \"myapp/guipanel\"\n\n// after: gate GUI code behind a build tag\n//go:build windows && gui\npackage guipanel","handlingStrategy":"fallback","validationCode":"// As with user32: pre-flight the environment outside the process, or gate imports.\n//go:build windows && gui\n// package gui // imports winc icon package only in GUI builds","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use full desktop/servercore container images when GUI deps are needed","Split headless services from GUI code with build tags","Verify DLL presence in the deploy image before shipping"],"tags":["windows","dll","init-time","environment","winc","panic","containers"],"backgroundTag":null,"analyzedSha":"0e754b1b40ba9044c2a1460e23b7c3de20fc5cf3","analyzedAt":"2026-08-15T14:17:36.034Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}