TencentCloud/TencentDB-Agent-Memory · error

DESTINATION_EXISTS

DESTINATION_EXISTS

Error message

DESTINATION_EXISTS: ${dstPrefix}

What it means

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).

Source

Thrown at MemoryCore/src/core/storage/adapter.ts:275

    const srcEntries = await this.backend.listObjects(srcPrefix, {
      maxKeys: 100_000,
      recursive: true,
    });

    // src 下没有任何对象 → 视为不存在
    const srcFiles = srcEntries.entries.filter((e) => !e.isDirectory);
    const srcExists = await this.backend.exists(srcPrefix);
    if (srcFiles.length === 0 && !srcExists) {
      throw new Error(`STORAGE_NOT_FOUND: ${srcPrefix}`);
    }

    if (!opts.overwrite) {
      const dstEntries = await this.backend.listObjects(dstPrefix, {
        maxKeys: 1000,
        recursive: true,
      });
      if (dstEntries.entries.some((e) => !e.isDirectory)) {
        throw new Error(`DESTINATION_EXISTS: ${dstPrefix}`);
      }
    }

    const srcNorm = srcPrefix.endsWith("/") ? srcPrefix : srcPrefix + "/";
    const dstNorm = dstPrefix.endsWith("/") ? dstPrefix : dstPrefix + "/";

    for (const entry of srcFiles) {
      // 计算相对路径
      let rel = entry.key;
      if (rel.startsWith(srcNorm)) rel = rel.slice(srcNorm.length);
      else if (rel === srcPrefix) rel = "";
      const dstKey = `${dstNorm}${rel}`;

      const obj = await this.backend.getObject(entry.key);
      if (!obj) continue;
      await this.backend.putObject(dstKey, obj.content, {
        contentType: obj.contentType,
        metadata: obj.metadata,

View on GitHub (pinned to 3efcd317b8)

Solutions

  1. Pass { overwrite: true } if replacing the destination is intended
  2. Use a unique destination prefix (timestamp/uuid suffix) per copy
  3. Delete or archive the existing destination prefix before copying
  4. Catch DESTINATION_EXISTS and prompt the user / choose a new destination

Example fix

// before
await adapter.copyTree('ws/a', 'backups/a', {}); // throws if backups/a has files
// after
await adapter.copyTree('ws/a', `backups/a-${Date.now()}`, {});
Defensive patterns

Strategy: validation

Validate before calling

const dstEntries = await adapter.list(dstPrefix);
if (dstEntries.some((e) => !e.isDirectory) && !opts.overwrite) {
  dstPrefix = `${dstPrefix}-${Date.now()}`; // pick a unique destination up front
}

Try / catch

try {
  await adapter.copyTree(src, dst, { overwrite: false });
} catch (e) {
  if (String(e.message).startsWith('DESTINATION_EXISTS:')) {
    await adapter.copyTree(src, dst, { overwrite: true }); // explicit overwrite decision
  } else throw e;
}

Prevention

When it happens

Trigger: Calling copyTree(srcPrefix, dstPrefix) without opts.overwrite when the destination prefix already contains one or more non-directory objects.

Common situations: 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.

Related errors


AI-assisted analysis of TencentCloud/TencentDB-Agent-Memory@3efcd317b8 (2026-09-01). Data as JSON: /api/errors/64edcd314e87fcec. Report an issue: GitHub.