{"record":{"id":"9c408ef4da0a3f35","repo":"linshenkx/prompt-optimizer","slug":"target-tag-cannot-be-empty","errorCode":null,"errorMessage":"Target tag cannot be empty","messagePattern":"Target tag cannot be empty","errorType":"validation","errorClass":"FavoriteValidationError","httpStatus":null,"severity":"warning","filePath":"packages/core/src/services/favorite/manager.ts","lineNumber":1046,"sourceCode":"          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);\n        if (!hasTargetTag) {\n          filteredTags.push({\n            tag: targetTag,\n            createdAt: Date.now()","sourceCodeStart":1028,"sourceCodeEnd":1064,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/core/src/services/favorite/manager.ts#L1028-L1064","documentation":"FavoriteValidationError thrown by mergeTags when targetTag is falsy — the destination tag for the merge must be a non-empty string.","triggerScenarios":"Calling mergeTags(['a'], '') or passing null/undefined as targetTag.","commonSituations":"Merge dialog with an unset target; target cleared by user before submission.","solutions":["Validate targetTag is a non-empty string before merging","Default the target to one of the source tags in UI flows"],"exampleFix":"// before\nawait manager.mergeTags(sources, target);\n\n// after\nif (sources.length && target) {\n  await manager.mergeTags(sources, target);\n}","handlingStrategy":"validation","validationCode":"if (targetTag) await manager.mergeTags(sourceTags, targetTag);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Default the merge target to a selected source tag"],"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"}