{"record":{"id":"64edcd314e87fcec","repo":"TencentCloud/TencentDB-Agent-Memory","slug":"destination-exists","errorCode":"DESTINATION_EXISTS","errorMessage":"DESTINATION_EXISTS: ${dstPrefix}","messagePattern":"DESTINATION_EXISTS: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"MemoryCore/src/core/storage/adapter.ts","lineNumber":275,"sourceCode":"    const srcEntries = await this.backend.listObjects(srcPrefix, {\n      maxKeys: 100_000,\n      recursive: true,\n    });\n\n    // src 下没有任何对象 → 视为不存在\n    const srcFiles = srcEntries.entries.filter((e) => !e.isDirectory);\n    const srcExists = await this.backend.exists(srcPrefix);\n    if (srcFiles.length === 0 && !srcExists) {\n      throw new Error(`STORAGE_NOT_FOUND: ${srcPrefix}`);\n    }\n\n    if (!opts.overwrite) {\n      const dstEntries = await this.backend.listObjects(dstPrefix, {\n        maxKeys: 1000,\n        recursive: true,\n      });\n      if (dstEntries.entries.some((e) => !e.isDirectory)) {\n        throw new Error(`DESTINATION_EXISTS: ${dstPrefix}`);\n      }\n    }\n\n    const srcNorm = srcPrefix.endsWith(\"/\") ? srcPrefix : srcPrefix + \"/\";\n    const dstNorm = dstPrefix.endsWith(\"/\") ? dstPrefix : dstPrefix + \"/\";\n\n    for (const entry of srcFiles) {\n      // 计算相对路径\n      let rel = entry.key;\n      if (rel.startsWith(srcNorm)) rel = rel.slice(srcNorm.length);\n      else if (rel === srcPrefix) rel = \"\";\n      const dstKey = `${dstNorm}${rel}`;\n\n      const obj = await this.backend.getObject(entry.key);\n      if (!obj) continue;\n      await this.backend.putObject(dstKey, obj.content, {\n        contentType: obj.contentType,\n        metadata: obj.metadata,","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/3efcd317b84146d6a08518ac0f7ee7c8a8d200ec/MemoryCore/src/core/storage/adapter.ts#L257-L293","documentation":"copyTree refuses to overwrite an existing destination. Unless opts.overwrite is true, it lists the destination prefix and throws DESTINATION_EXISTS if any file objects already exist there, protecting callers from clobbering data (e.g. backups).","triggerScenarios":"Calling copyTree(srcPrefix, dstPrefix) without opts.overwrite when the destination prefix already contains one or more non-directory objects.","commonSituations":"Running a backup/snapshot twice with the same destination name; a previous partial copy left objects behind; timestamped destination not actually unique (same second/collision); retry after a failed copy without cleanup.","solutions":["Pass { overwrite: true } if replacing the destination is intended","Use a unique destination prefix (timestamp/uuid suffix) per copy","Delete or archive the existing destination prefix before copying","Catch DESTINATION_EXISTS and prompt the user / choose a new destination"],"exampleFix":"// before\nawait adapter.copyTree('ws/a', 'backups/a', {}); // throws if backups/a has files\n// after\nawait adapter.copyTree('ws/a', `backups/a-${Date.now()}`, {});","handlingStrategy":"validation","validationCode":"const dstEntries = await adapter.list(dstPrefix);\nif (dstEntries.some((e) => !e.isDirectory) && !opts.overwrite) {\n  dstPrefix = `${dstPrefix}-${Date.now()}`; // pick a unique destination up front\n}","typeGuard":null,"tryCatchPattern":"try {\n  await adapter.copyTree(src, dst, { overwrite: false });\n} catch (e) {\n  if (String(e.message).startsWith('DESTINATION_EXISTS:')) {\n    await adapter.copyTree(src, dst, { overwrite: true }); // explicit overwrite decision\n  } else throw e;\n}","preventionTips":["Always generate unique destination prefixes (uuid/timestamp) for snapshots","Be explicit about overwrite intent — pass overwrite: true rather than relying on empty destinations","Clean up partial copies after failed operations to avoid phantom destinations","Expose an overwrite flag in user-facing copy commands instead of failing silently"],"tags":["storage","conflict","overwrite","copy"],"backgroundTag":"destination-already-exists","analyzedSha":"3efcd317b84146d6a08518ac0f7ee7c8a8d200ec","analyzedAt":"2026-09-01T05:44:22.276Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}