apache/dolphinscheduler · error · FileAlreadyExistsException
file: ${dstPath} already exists
Error message
file: ${dstPath} already exists What it means
OssStorageOperator.upload throws FileAlreadyExistsException when the destination OSS key exists and overwrite=false. Unlike the OBS operator which throws ObsException, this one throws the JDK FileAlreadyExistsException.
Source
Thrown at dolphinscheduler-storage-plugin/dolphinscheduler-storage-oss/src/main/java/org/apache/dolphinscheduler/plugin/storage/oss/OssStorageOperator.java:196
@Override
public void copy(String srcPath, String dstPath, boolean deleteSource, boolean overwrite) {
srcPath = transformAbsolutePathToOssKey(srcPath);
dstPath = transformAbsolutePathToOssKey(dstPath);
ossClient.copyObject(bucketName, srcPath, bucketName, dstPath);
if (deleteSource) {
ossClient.deleteObject(bucketName, srcPath);
}
}
@SneakyThrows
@Override
public void upload(String srcFile, String dstPath, boolean deleteSource, boolean overwrite) {
dstPath = transformAbsolutePathToOssKey(dstPath);
if (ossClient.doesObjectExist(bucketName, dstPath)) {
if (!overwrite) {
throw new FileAlreadyExistsException("file: " + dstPath + " already exists");
} else {
ossClient.deleteObject(bucketName, dstPath);
}
}
ossClient.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 = transformAbsolutePathToOssKey(filePath);
OSSObject ossObject = ossClient.getObject(bucketName, filePath);
try (
InputStreamReader inputStreamReader = new InputStreamReader(ossObject.getObjectContent());View on GitHub (pinned to 02eac45a1b)
Solutions
- Pass overwrite=true to replace the existing object
- Delete the destination object before uploading
- Use a unique dstPath per run
Example fix
// before
storageOperator.upload(src, dst, false, false);
// after
if (storageOperator.existsStorageFile(dst)) {
storageOperator.upload(src, dst, false, true);
} else {
storageOperator.upload(src, dst, false, false);
} Defensive patterns
Strategy: validation
Validate before calling
if (storageOperator.existsStorageFile(dstPath) && !overwrite) {
throw new IllegalStateException("Refusing to upload to existing path " + dstPath);
}
storageOperator.upload(srcFile, dstPath, deleteSource, overwrite); Try / catch
try {
storageOperator.upload(src, dst, false, false);
} catch (FileAlreadyExistsException e) {
log.warn("{} exists, retrying with overwrite", dst);
storageOperator.upload(src, dst, false, true);
} Prevention
- Set overwrite=true deliberately when re-uploading to fixed paths
- Version destination keys instead of overwriting when history matters
- Serialize uploads to the same destination across concurrent tasks
When it happens
Trigger: Calling upload(srcFile, dstPath, deleteSource, false) where ossClient.doesObjectExist reports the dstPath key already exists.
Common situations: Repeated uploads to a fixed resource path without overwrite; leftover object from a failed prior run; two tasks uploading to the same destination concurrently.
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
- bucketName: <bucketName> is not exists, you need to create t
- directory: ${directoryAbsolutePath} already exists
- bucketName: ${bucketName} is not exists, you need to create
AI-assisted analysis of apache/dolphinscheduler@02eac45a1b (2026-09-06).
Data as JSON: /api/errors/30fd567611894558.
Report an issue: GitHub.