{"record":{"id":"e69f06dfbdb75b28","repo":"linshenkx/prompt-optimizer","slug":"source-tag-list-cannot-be-empty","errorCode":null,"errorMessage":"Source tag list cannot be empty","messagePattern":"Source tag list cannot be empty","errorType":"validation","errorClass":"FavoriteValidationError","httpStatus":null,"severity":"warning","filePath":"packages/core/src/services/favorite/manager.ts","lineNumber":1042,"sourceCode":"              createdAt: Date.now()\n            });\n          }\n\n          return tagsList;\n        });\n      }\n\n      await this.updateStats();\n      return affectedCount;\n    } catch (error) {\n      const errorMessage = error instanceof Error ? error.message : String(error);\n      throw new FavoriteStorageError(`Failed to rename tag: ${errorMessage}`);\n    }\n  }\n\n  async mergeTags(sourceTags: string[], targetTag: string): Promise<number> {\n    if (!sourceTags || sourceTags.length === 0) {\n      throw new FavoriteValidationError('Source tag list cannot be empty');\n    }\n\n    if (!targetTag) {\n      throw new FavoriteValidationError('Target tag cannot be empty');\n    }\n\n    let affectedCount = 0;\n\n    try {\n      // 1. 更新独立标签库:删除所有源标签,确保目标标签存在\n      await this.storageProvider.updateData(this.STORAGE_KEYS.TAGS, (tags: FavoriteTag[] | null) => {\n        const tagsList = tags || [];\n\n        // 删除所有源标签\n        const filteredTags = tagsList.filter(t => !sourceTags.includes(t.tag));\n\n        // 确保目标标签存在\n        const hasTargetTag = filteredTags.some(t => t.tag === targetTag);","sourceCodeStart":1024,"sourceCodeEnd":1060,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/core/src/services/favorite/manager.ts#L1024-L1060","documentation":"FavoriteValidationError thrown by mergeTags when sourceTags is null, undefined, or an empty array. At least one source tag is required to merge.","triggerScenarios":"Calling mergeTags([], 'target') or mergeTags(null, 'target').","commonSituations":"UI allowing merge with no source tags selected; programmatic merge built from an empty selection.","solutions":["Require at least one selected source tag before enabling merge","Early-return when the selection is empty"],"exampleFix":"// before\nawait manager.mergeTags(selected, target);\n\n// after\nif (selected.length > 0 && target) {\n  await manager.mergeTags(selected, target);\n}","handlingStrategy":"validation","validationCode":"if (sourceTags?.length) await manager.mergeTags(sourceTags, targetTag);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Require at least one source selection in merge UI"],"tags":["validation","tags","merge","favorites"],"backgroundTag":"empty-input-validation","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}