{"record":{"id":"e1999cd0dcdf28ae","repo":"immich-app/immich","slug":"source-and-target-id-must-be-distinct","errorCode":null,"errorMessage":"Source and target id must be distinct","messagePattern":"Source and target id must be distinct","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"warning","filePath":"server/src/services/asset.service.ts","lineNumber":209,"sourceCode":"      sourceId,\n      targetId,\n      albums = true,\n      sidecar = true,\n      sharedLinks = true,\n      stack = true,\n      favorite = true,\n    }: AssetCopyDto,\n  ) {\n    await this.requireAccess({ auth, permission: Permission.AssetCopy, ids: [sourceId, targetId] });\n    const sourceAsset = await this.assetRepository.getForCopy(sourceId);\n    const targetAsset = await this.assetRepository.getForCopy(targetId);\n\n    if (!sourceAsset || !targetAsset) {\n      throw new BadRequestException('Both assets must exist');\n    }\n\n    if (sourceId === targetId) {\n      throw new BadRequestException('Source and target id must be distinct');\n    }\n\n    if (albums) {\n      await this.albumRepository.copyAlbums({ sourceAssetId: sourceId, targetAssetId: targetId });\n    }\n\n    if (sharedLinks) {\n      await this.sharedLinkAssetRepository.copySharedLinks({ sourceAssetId: sourceId, targetAssetId: targetId });\n    }\n\n    if (stack) {\n      await this.copyStack({ sourceAsset, targetAsset });\n    }\n\n    if (favorite) {\n      await this.assetRepository.update({ id: targetId, isFavorite: sourceAsset.isFavorite });\n    }\n","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/services/asset.service.ts#L191-L227","documentation":"In copy, copying an asset onto itself is rejected: after verifying both assets exist, sourceId === targetId throws BadRequestException('Source and target id must be distinct'). Self-copy is meaningless (would duplicate relations onto the same row) so it is blocked as an invalid argument.","triggerScenarios":"POST copy where the same asset id is passed as both sourceId and targetId — typically a client bug or a UI selection bug (same item picked twice).","commonSituations":"Drag-and-drop handlers attaching the same asset as both source and target; batch scripts iterating lists without checking pair distinctness; copy-paste of an id into both form fields.","solutions":["Add a client-side check: skip/flag pairs where sourceId === targetId before calling the API.","Fix the UI selection logic so a single asset cannot be both copy source and target.","If you intended duplication, use the appropriate duplicate/stack operation instead of copy."],"exampleFix":"// before\nawait api.copyAssets(asset.id, asset.id); // self-copy\n// after\nif (sourceId === targetId) return; // nothing to copy\nawait api.copyAssets(sourceId, targetId);","handlingStrategy":"validation","validationCode":"if (sourceId === targetId) throw new Error('Source and target must be distinct assets');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Guard all copy/transfer calls with a distinctness check","Fix selection UIs so the same item cannot be picked twice","In batch scripts, validate each (source, target) pair before invoking the API"],"tags":["bad-request","copy","duplicate-argument","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c","analyzedAt":"2026-09-15T07:20:19.675Z","contentChangedAt":"2026-09-15T07:20:19.675Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}