apache/dolphinscheduler · warning · FileAlreadyExistsException

directory: ${directoryAbsolutePath} already exists

Error message

directory: ${directoryAbsolutePath} already exists

What it means

ObsStorageOperator.createStorageDir throws FileAlreadyExistsException when a placeholder object (directory marker) already exists at the transformed OBS key. OBS has no real directories, so the operator first checks doesObjectExist on the zero-length key and refuses to overwrite an existing marker.

Source

Thrown at dolphinscheduler-storage-plugin/dolphinscheduler-storage-obs/src/main/java/org/apache/dolphinscheduler/plugin/storage/obs/ObsStorageOperator.java:96

    }

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

    @SneakyThrows
    @Override
    public void createStorageDir(String directoryAbsolutePath) {
        directoryAbsolutePath = transformAbsolutePathToObsKey(directoryAbsolutePath);
        if (obsClient.doesObjectExist(bucketName, directoryAbsolutePath)) {
            throw new FileAlreadyExistsException("directory: " + directoryAbsolutePath + " already exists");
        }
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentLength(0L);
        InputStream emptyContent = new ByteArrayInputStream(new byte[0]);
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, directoryAbsolutePath, emptyContent);
        obsClient.putObject(putObjectRequest);
    }

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

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

View on GitHub (pinned to 02eac45a1b)

Solutions

  1. Check existence first with existsStorageDir / delete the existing object before calling createStorageDir
  2. Catch FileAlreadyExistsException and treat it as success if the directory is expected to exist
  3. Use a unique directory path (e.g. timestamp/UUID suffix) for each run

Example fix

// before
storageOperator.createStorageDir(resourcePath);
// after
if (!storageOperator.existsStorageDir(resourcePath)) {
    storageOperator.createStorageDir(resourcePath);
}
Defensive patterns

Strategy: validation

Validate before calling

if (!storageOperator.existsStorageDir(directoryAbsolutePath)) {
    storageOperator.createStorageDir(directoryAbsolutePath);
}

Try / catch

try {
    storageOperator.createStorageDir(dir);
} catch (FileAlreadyExistsException e) {
    log.info("Directory {} already exists, skipping creation", dir);
}

Prevention

When it happens

Trigger: Calling createStorageDir(path) when the OBS bucket already contains an object whose key equals transformAbsolutePathToObsKey(path) — e.g. the directory was created earlier or a file with the exact key name exists.

Common situations: Re-running a workflow or setup script that creates resource directories; two processes racing to create the same directory; a file was previously uploaded using the same path that is now used as a directory.

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