{"record":{"id":"38baaa63aca74e9b","repo":"linshenkx/prompt-optimizer","slug":"electron-api-not-available-please-ensure-preload","errorCode":null,"errorMessage":"Electron API not available. Please ensure preload script is loaded and window.electronAPI.favoriteManager is accessible.","messagePattern":"Electron API not available\\. Please ensure preload script is loaded and window\\.electronAPI\\.favoriteManager is accessible\\.","errorType":"exception","errorClass":"FavoriteStorageError","httpStatus":null,"severity":"error","filePath":"packages/core/src/services/favorite/electron-proxy.ts","lineNumber":34,"sourceCode":"import { toErrorWithCode } from '../../utils/error'\nimport { safeSerializeArgs } from '../../utils/ipc-serialization'\n\ndeclare const window: {\n  electronAPI: {\n    favoriteManager: IFavoriteManager;\n  }\n};\n\n/**\n * Electron 收藏服务代理\n * 在渲染进程中通过 window.electronAPI 与主进程的收藏服务通信\n */\nexport class FavoriteManagerElectronProxy implements IFavoriteManager {\n\n  private ensureApiAvailable() {\n    const windowAny = window as any;\n    if (!windowAny?.electronAPI?.favoriteManager) {\n      throw new FavoriteStorageError(\n        'Electron API not available. Please ensure preload script is loaded and window.electronAPI.favoriteManager is accessible.',\n      );\n    }\n  }\n\n  private async invokeMethod<T>(method: string, ...args: any[]): Promise<T> {\n    this.ensureApiAvailable();\n    try {\n      const safeArgs = safeSerializeArgs(...args);\n      return await (window.electronAPI.favoriteManager as any)[method](...safeArgs);\n    } catch (error: any) {\n      // New i18n-style structured errors: pass through as-is so UI can translate via `code + params`.\n      if (typeof error?.code === 'string' && error.code.startsWith('error.')) {\n        throw toErrorWithCode(error)\n      }\n\n      // 将IPC错误转换为具体的错误类型\n      if (error.code === 'FAVORITE_NOT_FOUND') {","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/core/src/services/favorite/electron-proxy.ts#L16-L52","documentation":"Thrown by FavoriteManagerElectronProxy.ensureApiAvailable when window.electronAPI.favoriteManager is not present. The proxy delegates all favorite operations to Electron via IPC, so it refuses to run outside a properly configured Electron renderer with the preload script exposed.","triggerScenarios":"Instantiating/using FavoriteManagerElectronProxy in a plain browser tab, in tests/jsdom without mocking window.electronAPI, or in an Electron app where contextIsolation is on but the preload script does not expose favoriteManager on electronAPI.","commonSituations":"Running the app in a browser instead of Electron; preload script not listed in BrowserWindow webPreferences; contextIsolation/sandbox flags changed; preload bundle failed to load silently; version mismatch between core package and preload API surface.","solutions":["Verify the preload script is configured: webPreferences.preload points to the built preload bundle","Confirm the preload exposes favoriteManager under electronAPI (check spelling/shape) in the version you ship","If running in a browser/web build, use the web/local implementation of IFavoriteManager instead of the Electron proxy","In tests, mock window.electronAPI.favoriteManager before constructing the proxy"],"exampleFix":"// before\nconst mgr = new FavoriteManagerElectronProxy();\n// after (browser/tests)\n(window as any).electronAPI = { favoriteManager: fakeApi };\nconst mgr = new FavoriteManagerElectronProxy();","handlingStrategy":"type-guard","validationCode":"const hasElectronApi = () =>\n  typeof window !== 'undefined' && !!(window as any).electronAPI?.favoriteManager;","typeGuard":"const hasFavoriteElectronApi = (w: Window): w is Window & { electronAPI: { favoriteManager: object } } =>\n  !!(w as any).electronAPI?.favoriteManager;","tryCatchPattern":"if (!hasElectronApi()) { useWebFavoriteManager(); } else { useElectronProxy(); }","preventionTips":["Check window.electronAPI at app bootstrap and choose the implementation accordingly","Keep preload bundling in CI to catch missing exposures early","Mock electronAPI in tests"],"tags":["electron","preload","ipc","environment"],"backgroundTag":"electron-preload-api-missing","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}