{"record":{"id":"3b60410d689cce48","repo":"linshenkx/prompt-optimizer","slug":"favorite-not-found","errorCode":"FAVORITE_NOT_FOUND","errorMessage":"${error.id}","messagePattern":"\\$\\{error\\.id\\}","errorType":"exception","errorClass":"FavoriteNotFoundError","httpStatus":null,"severity":"error","filePath":"packages/core/src/services/favorite/electron-proxy.ts","lineNumber":53,"sourceCode":"        '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') {\n        throw new FavoriteNotFoundError(error.id || '');\n      }\n      if (error.code === 'FAVORITE_ALREADY_EXISTS') {\n        throw new FavoriteAlreadyExistsError(error.content || '');\n      }\n      if (error.code === 'CATEGORY_NOT_FOUND') {\n        throw new FavoriteCategoryNotFoundError(error.id || '');\n      }\n      if (error.code === 'VALIDATION_ERROR') {\n        throw new FavoriteValidationError(error.message || '');\n      }\n      if (error.code === 'STORAGE_ERROR') {\n        throw new FavoriteStorageError(error.message || '');\n      }\n      // Legacy: category already exists\n      if (error.code === 'CATEGORY_ALREADY_EXISTS') {\n        throw new FavoriteValidationError(error.message || 'Category already exists')\n      }\n      // 标签相关错误","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/core/src/services/favorite/electron-proxy.ts#L35-L71","documentation":"The Electron main process returned an IPC error with code FAVORITE_NOT_FOUND; the renderer proxy converts it to FavoriteNotFoundError carrying the favorite id. It means no favorite prompt with that id exists in storage (or it was deleted).","triggerScenarios":"Calling getFavorite/updateFavorite/setFavoritePromptAssetCurrentVersion/deleteFavoritePromptAssetVersion with a stale or nonexistent favorite id via the Electron proxy.","commonSituations":"UI holding a cached id after the favorite was removed on another window/device; deleted favorite still open in an editor; race between list refresh and delete; id typo or truncated id.","solutions":["Refresh the favorites list and retry with a current id","Catch FavoriteNotFoundError and remove the stale entry from UI state","Verify the id is passed unchanged (no trimming/encoding issues)","Check the favorite wasn't deleted by sync/import in another process"],"exampleFix":"// before\nawait favoriteManager.getFavorite(id);\n// after\ntry { return await favoriteManager.getFavorite(id); }\ncatch (e) { if (e instanceof FavoriteNotFoundError) return null; throw e; }","handlingStrategy":"try-catch","validationCode":"const exists = (await mgr.getFavorites()).some(f => f.id === id);","typeGuard":"const isFavoriteNotFound = (e: unknown): e is FavoriteNotFoundError => e instanceof FavoriteNotFoundError;","tryCatchPattern":"try { return await mgr.getFavorite(id); } catch (e) { if (isFavoriteNotFound(e)) return null; throw e; }","preventionTips":["Treat delete as idempotent and purge ids from UI state","Refresh lists after destructive operations","Never cache ids across sessions without revalidation"],"tags":["favorite","not-found","ipc","electron"],"backgroundTag":"entity-not-found","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}