apache/dolphinscheduler · error · FileAlreadyExistsException

directory: ${directoryAbsolutePath} already exists

Error message

directory: ${directoryAbsolutePath} already exists

What it means

GcsStorageOperator.createStorageDir creates a GCS 'directory' by writing an empty blob at the transformed key. If a blob already exists at that key it throws FileAlreadyExistsException rather than overwriting, since GCS directories are only prefix conventions.

Source

Thrown at dolphinscheduler-storage-plugin/dolphinscheduler-storage-gcs/src/main/java/org/apache/dolphinscheduler/plugin/storage/gcs/GcsStorageOperator.java:100

    }

    @Override
    public String getStorageBaseDirectory() {
        // All directory should end with File.separator
        if (resourceBaseAbsolutePath.startsWith("/")) {
            log.warn("{} -> {} should not start with / in Gcs", StorageConstants.RESOURCE_UPLOAD_PATH,
                    resourceBaseAbsolutePath);
            return resourceBaseAbsolutePath.substring(1);
        }
        return getStorageBaseDirectory();
    }

    @SneakyThrows
    @Override
    public void createStorageDir(String directoryAbsolutePath) {
        directoryAbsolutePath = transformAbsolutePathToGcsKey(directoryAbsolutePath);
        if (exists(directoryAbsolutePath)) {
            throw new FileAlreadyExistsException("directory: " + directoryAbsolutePath + " already exists");
        }
        BlobInfo blobInfo = BlobInfo.newBuilder(BlobId.of(bucketName, directoryAbsolutePath)).build();
        gcsStorage.create(blobInfo, EMPTY_STRING.getBytes(StandardCharsets.UTF_8));
    }

    @SneakyThrows
    @Override
    public void download(String srcFilePath, String dstFilePath, boolean overwrite) {
        srcFilePath = transformAbsolutePathToGcsKey(srcFilePath);

        File dstFile = new File(dstFilePath);
        if (dstFile.isDirectory()) {
            Files.delete(dstFile.toPath());
        } else {
            FileUtils.createDirectoryWithPermission(dstFile.getParentFile().toPath(), FileUtils.PERMISSION_755);
        }

        Blob blob = gcsStorage.get(BlobId.of(bucketName, srcFilePath));

View on GitHub (pinned to 02eac45a1b)

Solutions

  1. Check exists() first and skip creation if it returns true
  2. Delete the existing blob via gcsStorage/Blob.delete if overwrite is safe, then retry
  3. Use a unique directory path (tenant/timestamp scoped)

Example fix

// before
gcs.createStorageDir(dirPath);
// after
if (!gcs.exists(dirPath)) {
    gcs.createStorageDir(dirPath);
}
Defensive patterns

Strategy: validation

Validate before calling

if (gcs.exists(gcsKey)) { /* skip or pick another directory */ }

Try / catch

try {
    gcs.createStorageDir(dir);
} catch (FileAlreadyExistsException e) {
    log.info("GCS directory already exists, reusing: {}", dir);
}

Prevention

When it happens

Trigger: Calling createStorageDir(directoryAbsolutePath) when exists(directoryAbsolutePath) finds an existing blob at the GCS key — from a previous mkdir, a file uploaded to the same path, or a leftover marker blob.

Common situations: Re-running workflows that recreate the same resource directory; an uploaded file occupying the directory key; stale blobs after resource reorganization.

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/a7fa7fadeab9d1f5. Report an issue: GitHub.