{"record":{"id":"f5525045b8f58098","repo":"Molunerfinn/PicGo","slug":"failed-to-get-window-state","errorCode":null,"errorMessage":"Failed to get window state","messagePattern":"Failed to get window state","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/renderer/adapters/window-controls.ts","lineNumber":9,"sourceCode":"import { CLOSE_WINDOW, MAXIMIZE_WINDOW, MINIMIZE_WINDOW } from '#/events/constants'\nimport { IRPCActionType } from '~/universal/types/enum'\nimport { invokeRPC, sendToMain } from '@/utils/dataSender'\n\nexport const windowControlsAdapter = {\n  async getWindowState () {\n    const result = await invokeRPC<{ isMaximized: boolean }>(IRPCActionType.GET_WINDOW_STATE)\n    if (!result.success) {\n      throw new Error(result.error || 'Failed to get window state')\n    }\n\n    return result.data\n  },\n  closeWindow () {\n    sendToMain(CLOSE_WINDOW)\n  },\n  maximizeWindow () {\n    sendToMain(MAXIMIZE_WINDOW)\n  },\n  minimizeWindow () {\n    sendToMain(MINIMIZE_WINDOW)\n  },\n  openMiniWindow () {\n    sendToMain('openMiniWindow')\n  }\n}\n","sourceCodeStart":1,"sourceCodeEnd":27,"githubUrl":"https://github.com/Molunerfinn/PicGo/blob/07ec7068a5512344da093d49a8408fa63ba3421e/src/renderer/adapters/window-controls.ts#L1-L27","documentation":"getWindowState throws when the GET_WINDOW_STATE RPC fails, meaning no { isMaximized } envelope came back from the main process. The main handler (src/main/events/rpc/routes/system.ts:16) resolves the sender BrowserWindow and reads isMaximized(); if the handler throws (e.g. event.sender is destroyed) the RPC server converts it to a failure envelope and the adapter raises this Error. The literal text is the fallback when result.error is empty.","triggerScenarios":"Calling getWindowState() from a renderer whose WebContents is being destroyed/closed (BrowserWindow.fromWebContents returns undefined or isMaximized throws), or when the main-process RPC server is not running (app quitting) so invokeRPC fails/returns failure.","commonSituations":"Window restore/maximize logic running during window close or app shutdown; a minimized/tray-only session where the sender window no longer exists; race between renderer mount and main-process RPC server start().","solutions":["Guard the caller: skip window-state queries when the window is closing or the app is shutting down","Default to { isMaximized: false } in the calling component instead of letting the rejection propagate to the UI","Log result.error to confirm whether the sender window was destroyed; if so, re-query after the window is ready","Ensure rpcServer.start() has run before any renderer issues GET_WINDOW_STATE (normal app boot does this)"],"exampleFix":"// before\nconst { isMaximized } = await windowControlsAdapter.getWindowState()\n// after\nlet isMaximized = false\ntry {\n  isMaximized = (await windowControlsAdapter.getWindowState())?.isMaximized ?? false\n} catch {\n  // window gone or main busy; fall back to non-maximized\n}","handlingStrategy":"fallback","validationCode":"if (!document.hasFocus() || window.isClosed) {\n  return { isMaximized: false }\n}","typeGuard":"function isWindowState(v: unknown): v is { isMaximized: boolean } {\n  return typeof v === 'object' && v !== null && typeof (v as { isMaximized?: unknown }).isMaximized === 'boolean'\n}","tryCatchPattern":"try {\n  state = await windowControlsAdapter.getWindowState()\n} catch {\n  state = { isMaximized: false } // safe default\n}","preventionTips":["Only query window state while the window is alive and the app is fully booted","Default isMaximized to false on any failure instead of rejecting UI updates","Debounce state queries during window transitions (maximize/close)","Verify RPC server startup ordering in main before renderer windows load"],"tags":["ipc","rpc","window","electron"],"backgroundTag":"rpc-handler-failure","analyzedSha":"07ec7068a5512344da093d49a8408fa63ba3421e","analyzedAt":"2026-08-30T01:45:22.289Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}