java-native-access/jna · error · IllegalStateException
Window width and/or height were 0 even though GetWindowRect
Error message
Window width and/or height were 0 even though GetWindowRect did not appear to fail.
What it means
GDI32Util.getScreenshot throws this IllegalStateException when GetWindowRect reported success but the resulting rectangle has zero width or height, making a bitmap capture impossible. It is a sanity check guarding Blt/copy operations that would fail or produce an empty image.
Source
Thrown at contrib/platform/src/com/sun/jna/platform/win32/GDI32Util.java:85
* @return the window captured as a screenshot, or null if the BufferedImage
* doesn't construct properly
*
* @throws IllegalStateException if the rectangle from GetWindowRect has a
* width and/or height of 0. <br>
* if the device context acquired from the original HWND doesn't release
* properly
*/
public static BufferedImage getScreenshot(HWND target) {
RECT rect = new RECT();
if (!User32.INSTANCE.GetWindowRect(target, rect)) {
throw new Win32Exception(Native.getLastError());
}
Rectangle jRectangle = rect.toRectangle();
int windowWidth = jRectangle.width;
int windowHeight = jRectangle.height;
if (windowWidth == 0 || windowHeight == 0) {
throw new IllegalStateException("Window width and/or height were 0 even though GetWindowRect did not appear to fail.");
}
HDC hdcTarget = User32.INSTANCE.GetDC(target);
if (hdcTarget == null) {
throw new Win32Exception(Native.getLastError());
}
Win32Exception we = null;
// device context used for drawing
HDC hdcTargetMem = null;
// handle to the bitmap to be drawn to
HBITMAP hBitmap = null;
// original display surface associated with the device context
HANDLE hOriginal = null;
View on GitHub (pinned to d036ad9781)
Solutions
- Ensure the target window is visible/restored before capture (ShowWindow with SW_RESTORE, or wait for it to be shown)
- Check IsWindowVisible and IsIconic and restore/bring the window forward first
- Verify the HWND is the correct top-level window, not a zero-size child or dummy handle
- If the zero size is legitimate for your case, skip the screenshot instead of calling getScreenshot
Example fix
// before
BufferedImage img = GDI32Util.getScreenshot(hwnd);
// after
if (!User32.INSTANCE.IsWindowVisible(hwnd) || User32.INSTANCE.IsIconic(hwnd)) {
User32.INSTANCE.ShowWindow(hwnd, new WinDef.SW_NOSHOW(SW_RESTORE));
}
RECT rect = new RECT();
User32.INSTANCE.GetWindowRect(hwnd, rect);
if (rect.toRectangle().width > 0 && rect.toRectangle().height > 0) {
BufferedImage img = GDI32Util.getScreenshot(hwnd);
} Defensive patterns
Strategy: validation
Validate before calling
RECT r = new RECT();
if (!User32.INSTANCE.GetWindowRect(hwnd, r)) throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
if (r.toRectangle().width == 0 || r.toRectangle().height == 0) {
User32.INSTANCE.ShowWindow(hwnd, 9 /* SW_RESTORE */);
} Type guard
boolean isScreenshottable(WinDef.HWND hwnd) {
RECT r = new RECT();
return User32.INSTANCE.IsWindowVisible(hwnd)
&& !User32.INSTANCE.IsIconic(hwnd)
&& User32.INSTANCE.GetWindowRect(hwnd, r)
&& r.toRectangle().width > 0 && r.toRectangle().height > 0;
} Try / catch
try {
BufferedImage img = GDI32Util.getScreenshot(hwnd);
} catch (IllegalStateException e) {
// window zero-size: restore and retry once
User32.INSTANCE.ShowWindow(hwnd, 9);
BufferedImage img = GDI32Util.getScreenshot(hwnd);
} Prevention
- Restore/un-minimize the window and wait until it is visible before capturing
- Check IsIconic/IsWindowVisible and GetWindowRect dimensions before calling getScreenshot
- Handle windows that legitimately have zero size by skipping capture
When it happens
Trigger: Capturing a window that is minimized, not yet shown (zero-size client area), or whose rect conversion yields 0 dimensions; passing an HWND of a hidden window.
Common situations: Screenshotting a minimized window via automation; capturing during window creation before layout; targeting a message-only or zero-size window.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Device context did not release properly.
- Invalid data length:
- Invalid guid length:
- Missing variable value separator in
- FileMonitor not implemented for " + os
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/8d635b583e4eb5d9.
Report an issue: GitHub.