linshenkx/prompt-optimizer · warning · FavoriteAlreadyExistsError

FAVORITE_ALREADY_EXISTS

FAVORITE_ALREADY_EXISTS

Error message

${error.content}

What it means

Main process reported FAVORITE_ALREADY_EXISTS; converted to FavoriteAlreadyExistsError with the conflicting content as the message. Duplicate favorites are rejected by the storage layer.

Source

Thrown at packages/core/src/services/favorite/electron-proxy.ts:56

  }

  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') {
        throw new FavoriteNotFoundError(error.id || '');
      }
      if (error.code === 'FAVORITE_ALREADY_EXISTS') {
        throw new FavoriteAlreadyExistsError(error.content || '');
      }
      if (error.code === 'CATEGORY_NOT_FOUND') {
        throw new FavoriteCategoryNotFoundError(error.id || '');
      }
      if (error.code === 'VALIDATION_ERROR') {
        throw new FavoriteValidationError(error.message || '');
      }
      if (error.code === 'STORAGE_ERROR') {
        throw new FavoriteStorageError(error.message || '');
      }
      // Legacy: category already exists
      if (error.code === 'CATEGORY_ALREADY_EXISTS') {
        throw new FavoriteValidationError(error.message || 'Category already exists')
      }
      // 标签相关错误
      if (error.code === 'TAG_ALREADY_EXISTS') {
        throw new FavoriteTagAlreadyExistsError(error.tag || '');
      }

View on GitHub (pinned to 3e677b1d9f)

Solutions

  1. Catch FavoriteAlreadyExistsError and surface a 'already saved' message instead of failing
  2. Debounce/disable the save button while a request is in flight
  3. Dedupe against the current list before calling addFavorite
  4. For imports, skip-or-update strategy rather than blind insert

Example fix

// before
await mgr.addFavorite(fav);
// after
try { await mgr.addFavorite(fav); }
catch (e) { if (e instanceof FavoriteAlreadyExistsError) { toast('Already favorited'); return; } throw e; }
Defensive patterns

Strategy: try-catch

Validate before calling

const dup = (await mgr.getFavorites()).some(f => f.content === fav.content);

Type guard

const isAlreadyExists = (e: unknown): e is FavoriteAlreadyExistsError => e instanceof FavoriteAlreadyExistsError;

Try / catch

try { await mgr.addFavorite(fav); } catch (e) { if (isAlreadyExists(e)) { showToast('Already favorited'); return; } throw e; }

Prevention

When it happens

Trigger: addFavorite (or import) with content identical to an existing favorite triggers the uniqueness check in the Electron main process.

Common situations: User double-clicks a save button; retry after timeout re-submits; import file contains entries already stored; no client-side dedupe before submit.

Related errors


AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27). Data as JSON: /api/errors/2e69be28ff63e9f7. Report an issue: GitHub.