linshenkx/prompt-optimizer · error · FavoriteStorageError
Electron API not available. Please ensure preload script is
Error message
Electron API not available. Please ensure preload script is loaded and window.electronAPI.favoriteManager is accessible.
What it means
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.
Source
Thrown at packages/core/src/services/favorite/electron-proxy.ts:34
import { toErrorWithCode } from '../../utils/error'
import { safeSerializeArgs } from '../../utils/ipc-serialization'
declare const window: {
electronAPI: {
favoriteManager: IFavoriteManager;
}
};
/**
* Electron 收藏服务代理
* 在渲染进程中通过 window.electronAPI 与主进程的收藏服务通信
*/
export class FavoriteManagerElectronProxy implements IFavoriteManager {
private ensureApiAvailable() {
const windowAny = window as any;
if (!windowAny?.electronAPI?.favoriteManager) {
throw new FavoriteStorageError(
'Electron API not available. Please ensure preload script is loaded and window.electronAPI.favoriteManager is accessible.',
);
}
}
private async invokeMethod<T>(method: string, ...args: any[]): Promise<T> {
this.ensureApiAvailable();
try {
const safeArgs = safeSerializeArgs(...args);
return await (window.electronAPI.favoriteManager as any)[method](...safeArgs);
} catch (error: any) {
// New i18n-style structured errors: pass through as-is so UI can translate via `code + params`.
if (typeof error?.code === 'string' && error.code.startsWith('error.')) {
throw toErrorWithCode(error)
}
// 将IPC错误转换为具体的错误类型
if (error.code === 'FAVORITE_NOT_FOUND') {View on GitHub (pinned to 3e677b1d9f)
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
Example fix
// before
const mgr = new FavoriteManagerElectronProxy();
// after (browser/tests)
(window as any).electronAPI = { favoriteManager: fakeApi };
const mgr = new FavoriteManagerElectronProxy(); Defensive patterns
Strategy: type-guard
Validate before calling
const hasElectronApi = () => typeof window !== 'undefined' && !!(window as any).electronAPI?.favoriteManager;
Type guard
const hasFavoriteElectronApi = (w: Window): w is Window & { electronAPI: { favoriteManager: object } } =>
!!(w as any).electronAPI?.favoriteManager; Try / catch
if (!hasElectronApi()) { useWebFavoriteManager(); } else { useElectronProxy(); } Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- GENERATION_FAILED
- CONFIG_INVALID
- Desktop remote storage IPC is unavailable
- FAVORITE_NOT_FOUND
- FAVORITE_ALREADY_EXISTS
AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27).
Data as JSON: /api/errors/38baaa63aca74e9b.
Report an issue: GitHub.