wailsapp/wails · error · Error
Invalid JSON passed to callback: ${e.message}. Message: ${in
Error message
Invalid JSON passed to callback: ${e.message}. Message: ${incomingMessage} What it means
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.
Source
Thrown at v2/internal/frontend/runtime/desktop/calls.js:167
};
/**
* Called by the backend to return data to a previously called
* binding invocation
*
* @export
* @param {string} incomingMessage
*/
export function Callback(incomingMessage) {
// Parse the message
let message;
try {
message = JSON.parse(incomingMessage);
} catch (e) {
const error = `Invalid JSON passed to callback: ${e.message}. Message: ${incomingMessage}`;
runtime.LogDebug(error);
throw new Error(error);
}
let callbackID = message.callbackid;
let callbackData = callbacks[callbackID];
if (!callbackData) {
const error = `Callback '${callbackID}' not registered!!!`;
console.error(error); // eslint-disable-line
throw new Error(error);
}
clearTimeout(callbackData.timeoutHandle);
delete callbacks[callbackID];
if (message.error) {
const err = message.error instanceof Error ? message.error : new Error(message.error);
callbackData.reject(err);
} else {
callbackData.resolve(message.result);
}View on GitHub (pinned to 0e754b1b40)
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.
Example fix
// before
w32.PatBlt(hdc, 0, 0, width, height, w32.SRCCOPY) // unsupported rop -> panic
// after
w32.PatBlt(hdc, 0, 0, width, height, w32.PATCOPY) // PatBlt-supported rop
if width <= 0 || height <= 0 {
return // nothing to fill
} Defensive patterns
Strategy: validation
Validate before calling
func canPatBlt(hdc w32.HDC, w, h int, rop uint) bool {
if hdc == 0 || w <= 0 || h <= 0 {
return false
}
switch rop {
case w32.PATCOPY, w32.PATINVERT, w32.DSTINVERT, w32.BLACKNESS, w32.WHITENESS:
return true
}
return false
} Try / catch
defer func() {
if r := recover(); r != nil {
if msg, ok := r.(string); ok && strings.HasPrefix(msg, "PatBlt failed") {
log.Printf("paint fill skipped: %v (lasterr=%d)", r, w32.GetLastError())
return
}
panic(r)
}
}()
w32.PatBlt(hdc, 0, 0, w, h, w32.PATCOPY) Prevention
- 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).
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Callback '${callbackID}' not registered!!!
- Invalid JSON passed to Notify: ${notifyMessage}
- CancellablePromise does not support transparent subclassing.
- CancellablePromise.prototype.then called on an invalid objec
- CancellablePromise.prototype.finally called on an invalid ob
AI-assisted analysis of wailsapp/wails@0e754b1b40 (2026-08-15).
Data as JSON: /api/errors/8122d3a40856da44.
Report an issue: GitHub.