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
- Check existence first with existsStorageDir / delete the existing object before calling createStorageDir
- Catch FileAlreadyExistsException and treat it as success if the directory is expected to exist
- 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
- Make directory creation idempotent: existence check before create
- Treat FileAlreadyExistsException as success in setup scripts
- Use run-scoped unique directory keys to avoid collisions between concurrent workflows
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
- file: ${dstPath} already exists
- directory: ${directory} already exists
- The directory ${directoryAbsolutePath} already exists in the
- bucketName: ${bucketName} is not exists, you need to create
- file: ${dstPath} already exists
AI-assisted analysis of apache/dolphinscheduler@02eac45a1b (2026-09-06).
Data as JSON: /api/errors/cf92ed873526c9b6.
Report an issue: GitHub.