Molunerfinn/PicGo · warning

Failed to get window state

Error message

Failed to get window state

What it means

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.

Source

Thrown at src/renderer/adapters/window-controls.ts:9

import { CLOSE_WINDOW, MAXIMIZE_WINDOW, MINIMIZE_WINDOW } from '#/events/constants'
import { IRPCActionType } from '~/universal/types/enum'
import { invokeRPC, sendToMain } from '@/utils/dataSender'

export const windowControlsAdapter = {
  async getWindowState () {
    const result = await invokeRPC<{ isMaximized: boolean }>(IRPCActionType.GET_WINDOW_STATE)
    if (!result.success) {
      throw new Error(result.error || 'Failed to get window state')
    }

    return result.data
  },
  closeWindow () {
    sendToMain(CLOSE_WINDOW)
  },
  maximizeWindow () {
    sendToMain(MAXIMIZE_WINDOW)
  },
  minimizeWindow () {
    sendToMain(MINIMIZE_WINDOW)
  },
  openMiniWindow () {
    sendToMain('openMiniWindow')
  }
}

View on GitHub (pinned to 07ec7068a5)

Solutions

  1. Guard the caller: skip window-state queries when the window is closing or the app is shutting down
  2. Default to { isMaximized: false } in the calling component instead of letting the rejection propagate to the UI
  3. Log result.error to confirm whether the sender window was destroyed; if so, re-query after the window is ready
  4. Ensure rpcServer.start() has run before any renderer issues GET_WINDOW_STATE (normal app boot does this)

Example fix

// before
const { isMaximized } = await windowControlsAdapter.getWindowState()
// after
let isMaximized = false
try {
  isMaximized = (await windowControlsAdapter.getWindowState())?.isMaximized ?? false
} catch {
  // window gone or main busy; fall back to non-maximized
}
Defensive patterns

Strategy: fallback

Validate before calling

if (!document.hasFocus() || window.isClosed) {
  return { isMaximized: false }
}

Type guard

function isWindowState(v: unknown): v is { isMaximized: boolean } {
  return typeof v === 'object' && v !== null && typeof (v as { isMaximized?: unknown }).isMaximized === 'boolean'
}

Try / catch

try {
  state = await windowControlsAdapter.getWindowState()
} catch {
  state = { isMaximized: false } // safe default
}

Prevention

When it happens

Trigger: 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.

Common situations: 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().

Related errors


AI-assisted analysis of Molunerfinn/PicGo@07ec7068a5 (2026-08-30). Data as JSON: /api/errors/f5525045b8f58098. Report an issue: GitHub.