apache/dolphinscheduler · error · FileAlreadyExistsException

The file ${dstPath} already exists in the bucket ${bucketNam

Error message

The file ${dstPath} already exists in the bucket ${bucketName} and overwrite is not allowed.

What it means

S3StorageOperator.upload refuses to write srcFile to the S3 key dstPath when an object already exists at that key and the overwrite flag is false. Before copying, it checks doesObjectExist; only when overwrite=true does it delete the existing object and proceed. This is a safety guard against silently clobbering stored resources.

Source

Thrown at dolphinscheduler-storage-plugin/dolphinscheduler-storage-s3/src/main/java/org/apache/dolphinscheduler/plugin/storage/s3/S3StorageOperator.java:182

        if (resourceMetaData.isDirectory()) {
            throw new UnsupportedOperationException("S3 does not support copying directories.");
        }
        s3Client.copyObject(bucketName, srcPath, bucketName, dstPath);
        if (deleteSource) {
            s3Client.deleteObject(bucketName, srcPath);
        }
    }

    @SneakyThrows
    @Override
    public void upload(String srcFile, String dstPath, boolean deleteSource, boolean overwrite) {
        dstPath = transformAbsolutePathToS3Key(dstPath);

        if (s3Client.doesObjectExist(bucketName, dstPath)) {
            if (overwrite) {
                s3Client.deleteObject(bucketName, dstPath);
            } else {
                throw new FileAlreadyExistsException("The file " + dstPath + " already exists in the bucket "
                        + bucketName + " and overwrite is not allowed.");
            }
        }

        s3Client.putObject(bucketName, dstPath, new File(srcFile));

        if (deleteSource) {
            Files.delete(Paths.get(srcFile));
        }
    }

    @SneakyThrows
    @Override
    public List<String> fetchFileContent(String filePath, int skipLineNums, int limit) {
        filePath = transformAbsolutePathToS3Key(filePath);
        S3Object s3Object = s3Client.getObject(bucketName, filePath);
        try (
                InputStreamReader inputStreamReader = new InputStreamReader(s3Object.getObjectContent());

View on GitHub (pinned to 02eac45a1b)

Solutions

  1. Set the overwrite flag to true when re-uploads to the same path are intentional
  2. Delete the existing object first (or use a new unique dstPath) before uploading
  3. Use a versioned/unique destination path (e.g. timestamp suffix) to avoid collisions

Example fix

// before
storageOperator.upload(srcFile, dstPath, false);
// after
storageOperator.upload(srcFile, dstPath, true); // intentional overwrite
Defensive patterns

Strategy: validation

Validate before calling

if (storageOperator.exists(dstPath) && !overwrite) {
    throw new IllegalStateException("Destination exists, choose overwrite or a new path: " + dstPath);
}
storageOperator.upload(srcFile, dstPath, overwrite);

Try / catch

try {
    storageOperator.upload(srcFile, dstPath, false);
} catch (FileAlreadyExistsException e) {
    log.warn("Target exists: {}", e.getMessage()); // choose new path or overwrite
}

Prevention

When it happens

Trigger: Calling upload(srcFile, dstPath, false) (or an upload API without overwrite enabled) while the resolved S3 key already holds an object in bucketName. Happens on re-running a workflow/task that uploads to the same resource path.

Common situations: Re-uploading a resource file with the same name; user scripts that regenerate the same resource path; migrating resources into a bucket that already contains the target key; forgetting to set resource.upload.overwrite or pass overwrite=true.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


AI-assisted analysis of apache/dolphinscheduler@02eac45a1b (2026-09-06). Data as JSON: /api/errors/05abc6546f35a55e. Report an issue: GitHub.