{"record":{"id":"ee653dbbc1960d52","repo":"apache/dolphinscheduler","slug":"the-directory-directoryabsolutepath-already-exi","errorCode":null,"errorMessage":"The directory ${directoryAbsolutePath} already exists in the bucket ${bucketName}","messagePattern":"The directory (.+?) already exists in the bucket (.+?)","errorType":"exception","errorClass":"FileAlreadyExistsException","httpStatus":null,"severity":"warning","filePath":"dolphinscheduler-storage-plugin/dolphinscheduler-storage-s3/src/main/java/org/apache/dolphinscheduler/plugin/storage/s3/S3StorageOperator.java","lineNumber":100,"sourceCode":"        if (resourceBaseAbsolutePath.startsWith(\"/\")) {\n            log.warn(\"{} -> {} should not start with / in s3\", StorageConstants.RESOURCE_UPLOAD_PATH,\n                    resourceBaseAbsolutePath);\n            return resourceBaseAbsolutePath.substring(1);\n        }\n        return resourceBaseAbsolutePath;\n    }\n\n    @Override\n    public void close() throws IOException {\n        s3Client.shutdown();\n    }\n\n    @SneakyThrows\n    @Override\n    public void createStorageDir(String directoryAbsolutePath) {\n        directoryAbsolutePath = transformAbsolutePathToS3Key(directoryAbsolutePath);\n        if (s3Client.doesObjectExist(bucketName, directoryAbsolutePath)) {\n            throw new FileAlreadyExistsException(\n                    \"The directory \" + directoryAbsolutePath + \" already exists in the bucket \" + bucketName);\n        }\n        ObjectMetadata metadata = new ObjectMetadata();\n        metadata.setContentLength(0);\n        InputStream emptyContent = new ByteArrayInputStream(new byte[0]);\n        PutObjectRequest putObjectRequest =\n                new PutObjectRequest(bucketName, directoryAbsolutePath, emptyContent, metadata);\n        s3Client.putObject(putObjectRequest);\n    }\n\n    @SneakyThrows\n    @Override\n    public void download(String srcFilePath,\n                         String dstFilePath,\n                         boolean overwrite) {\n        srcFilePath = transformAbsolutePathToS3Key(srcFilePath);\n        File dstFile = new File(dstFilePath);\n        if (dstFile.isDirectory()) {","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-storage-plugin/dolphinscheduler-storage-s3/src/main/java/org/apache/dolphinscheduler/plugin/storage/s3/S3StorageOperator.java#L82-L118","documentation":"S3StorageOperator.createStorageDir throws FileAlreadyExistsException when an object already exists at the transformed S3 key in the given bucket. S3 'directories' are zero-byte key markers, so an existing object at that key prevents directory creation.","triggerScenarios":"Calling createStorageDir(directoryAbsolutePath) when s3Client.doesObjectExist(bucketName, s3Key) is true — the marker or a file at that exact key already exists.","commonSituations":"Re-running workflows that provision the same resource directory; a previous task uploaded a file using the key now intended as a directory; concurrent task instances creating the same directory.","solutions":["Check existence (existsStorageDir) before creating, or delete the object first","Catch FileAlreadyExistsException and treat it as success for idempotent setup","Generate unique directory keys per run"],"exampleFix":"// before\ns3StorageOperator.createStorageDir(resourceDir);\n// after\nif (!s3StorageOperator.existsStorageDir(resourceDir)) {\n    s3StorageOperator.createStorageDir(resourceDir);\n}","handlingStrategy":"validation","validationCode":"if (!s3StorageOperator.existsStorageDir(directoryAbsolutePath)) {\n    s3StorageOperator.createStorageDir(directoryAbsolutePath);\n}","typeGuard":null,"tryCatchPattern":"try {\n    s3StorageOperator.createStorageDir(key);\n} catch (FileAlreadyExistsException e) {\n    log.info(\"S3 directory {} already exists in bucket, skipping\", key);\n}","preventionTips":["Make S3 directory creation idempotent (check first or ignore the exception)","Never upload files to keys you also use as directory markers","Use execution-scoped key prefixes to prevent cross-run collisions"],"tags":["storage","s3","file-already-exists","idempotency"],"backgroundTag":"file-already-exists","analyzedSha":"02eac45a1b6676e639fcbfb4be2243de5771b05d","analyzedAt":"2026-09-06T17:43:00.555Z","contentChangedAt":"2026-09-06T17:43:00.555Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}