{"record":{"id":"8122d3a40856da44","repo":"wailsapp/wails","slug":"invalid-json-passed-to-callback-e-message-mes","errorCode":null,"errorMessage":"Invalid JSON passed to callback: ${e.message}. Message: ${incomingMessage}","messagePattern":"Invalid JSON passed to callback: (.+?)\\. Message: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v2/internal/frontend/runtime/desktop/calls.js","lineNumber":167,"sourceCode":"};\n\n\n/**\n * Called by the backend to return data to a previously called\n * binding invocation\n *\n * @export\n * @param {string} incomingMessage\n */\nexport function Callback(incomingMessage) {\n\t// Parse the message\n\tlet message;\n\ttry {\n\t\tmessage = JSON.parse(incomingMessage);\n\t} catch (e) {\n\t\tconst error = `Invalid JSON passed to callback: ${e.message}. Message: ${incomingMessage}`;\n\t\truntime.LogDebug(error);\n\t\tthrow new Error(error);\n\t}\n\tlet callbackID = message.callbackid;\n\tlet callbackData = callbacks[callbackID];\n\tif (!callbackData) {\n\t\tconst error = `Callback '${callbackID}' not registered!!!`;\n\t\tconsole.error(error); // eslint-disable-line\n\t\tthrow new Error(error);\n\t}\n\tclearTimeout(callbackData.timeoutHandle);\n\n\tdelete callbacks[callbackID];\n\n\tif (message.error) {\n\t\tconst err = message.error instanceof Error ? message.error : new Error(message.error);\n\t\tcallbackData.reject(err);\n\t} else {\n\t\tcallbackData.resolve(message.result);\n\t}","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/wailsapp/wails/blob/0e754b1b40ba9044c2a1460e23b7c3de20fc5cf3/v2/internal/frontend/runtime/desktop/calls.js#L149-L185","documentation":"PatBlt fills a rectangle on a device context with the currently selected brush using the given raster operation. The w32 wrapper calls gdi32.PatBlt via syscall and panics with 'PatBlt failed' when the API returns 0 (FALSE), which Windows uses to signal failure. The panic discards the real reason; the actual code is only available via GetLastError immediately after the call. Typical causes are an invalid or destroyed HDC, a rectangle with zero/negative extents, or a raster-op code PatBlt does not support.","triggerScenarios":"Calling w32.PatBlt with an HDC that was deleted via DeleteDC, using a dwRop other than PATCOPY, PATINVERT, DSTINVERT, BLACKNESS, or WHITENESS (PatBlt rejects SRCCOPY-style rop codes), passing zero width/height, or filling on a DC whose selected brush was deleted while still selected.","commonSituations":"Drawing background rects in a custom-paint path during window teardown when the paint DC is already released; porting code from BitBlt and reusing an incompatible rop constant; intermixing w32 direct calls with another framework that owns and disposes the DC.","solutions":["Verify the HDC is still valid and not double-released: every GetDC must have a matching ReleaseDC and every BeginPaint an EndPaint before any PatBlt call.","Use only rop codes PatBlt supports: PATCOPY, PATINVERT, DSTINVERT, BLACKNESS, WHITENESS.","Check width/height are positive before calling; compute them from window client rects that can be zero during minimize.","Immediately after a failure, capture w32.GetLastError() (or set a breakpoint on the panic and inspect errno from the lazy syscall call) to identify the exact GDI error such as ERROR_INVALID_HANDLE.","If the panic aborts the app at shutdown, gate painting behind a 'window is closing' check so draw code stops before the DC dies."],"exampleFix":"// before\nw32.PatBlt(hdc, 0, 0, width, height, w32.SRCCOPY) // unsupported rop -> panic\n\n// after\nw32.PatBlt(hdc, 0, 0, width, height, w32.PATCOPY) // PatBlt-supported rop\nif width <= 0 || height <= 0 {\n\treturn // nothing to fill\n}","handlingStrategy":"validation","validationCode":"func canPatBlt(hdc w32.HDC, w, h int, rop uint) bool {\n\tif hdc == 0 || w <= 0 || h <= 0 {\n\t\treturn false\n\t}\n\tswitch rop {\n\tcase w32.PATCOPY, w32.PATINVERT, w32.DSTINVERT, w32.BLACKNESS, w32.WHITENESS:\n\t\treturn true\n\t}\n\treturn false\n}","typeGuard":null,"tryCatchPattern":"defer func() {\n\tif r := recover(); r != nil {\n\t\tif msg, ok := r.(string); ok && strings.HasPrefix(msg, \"PatBlt failed\") {\n\t\t\tlog.Printf(\"paint fill skipped: %v (lasterr=%d)\", r, w32.GetLastError())\n\t\t\treturn\n\t\t}\n\t\tpanic(r)\n\t}\n}()\nw32.PatBlt(hdc, 0, 0, w, h, w32.PATCOPY)","preventionTips":["Only use rop codes PatBlt supports (PATCOPY, PATINVERT, DSTINVERT, BLACKNESS, WHITENESS).","Never paint outside the BeginPaint/EndPaint or GetDC/ReleaseDC scope that owns the HDC.","Skip drawing when the window is closing or minimized (zero client rect)."],"tags":["windows","gdi","syscall","panic","drawing"],"backgroundTag":null,"analyzedSha":"0e754b1b40ba9044c2a1460e23b7c3de20fc5cf3","analyzedAt":"2026-08-15T14:17:36.034Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}