{"record":{"id":"cf92ed873526c9b6","repo":"apache/dolphinscheduler","slug":"directory-directoryabsolutepath-already-exists-cf92ed","errorCode":null,"errorMessage":"directory: ${directoryAbsolutePath} already exists","messagePattern":"directory: (.+?) already exists","errorType":"exception","errorClass":"FileAlreadyExistsException","httpStatus":null,"severity":"warning","filePath":"dolphinscheduler-storage-plugin/dolphinscheduler-storage-obs/src/main/java/org/apache/dolphinscheduler/plugin/storage/obs/ObsStorageOperator.java","lineNumber":96,"sourceCode":"    }\n\n    @Override\n    public String getStorageBaseDirectory() {\n        // All directory should end with File.separator\n        if (resourceBaseAbsolutePath.startsWith(\"/\")) {\n            log.warn(\"{} -> {} should not start with / in obs\", StorageConstants.RESOURCE_UPLOAD_PATH,\n                    resourceBaseAbsolutePath);\n            return resourceBaseAbsolutePath.substring(1);\n        }\n        return resourceBaseAbsolutePath;\n    }\n\n    @SneakyThrows\n    @Override\n    public void createStorageDir(String directoryAbsolutePath) {\n        directoryAbsolutePath = transformAbsolutePathToObsKey(directoryAbsolutePath);\n        if (obsClient.doesObjectExist(bucketName, directoryAbsolutePath)) {\n            throw new FileAlreadyExistsException(\"directory: \" + directoryAbsolutePath + \" already exists\");\n        }\n        ObjectMetadata metadata = new ObjectMetadata();\n        metadata.setContentLength(0L);\n        InputStream emptyContent = new ByteArrayInputStream(new byte[0]);\n        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, directoryAbsolutePath, emptyContent);\n        obsClient.putObject(putObjectRequest);\n    }\n\n    @SneakyThrows\n    @Override\n    public void download(String srcFilePath, String dstFilePath, boolean overwrite) {\n        srcFilePath = transformAbsolutePathToObsKey(srcFilePath);\n\n        File dstFile = new File(dstFilePath);\n        if (dstFile.isDirectory()) {\n            Files.delete(dstFile.toPath());\n        } else {\n            FileUtils.createDirectoryWithPermission(dstFile.getParentFile().toPath(), FileUtils.PERMISSION_755);","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-storage-plugin/dolphinscheduler-storage-obs/src/main/java/org/apache/dolphinscheduler/plugin/storage/obs/ObsStorageOperator.java#L78-L114","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nstorageOperator.createStorageDir(resourcePath);\n// after\nif (!storageOperator.existsStorageDir(resourcePath)) {\n    storageOperator.createStorageDir(resourcePath);\n}","handlingStrategy":"validation","validationCode":"if (!storageOperator.existsStorageDir(directoryAbsolutePath)) {\n    storageOperator.createStorageDir(directoryAbsolutePath);\n}","typeGuard":null,"tryCatchPattern":"try {\n    storageOperator.createStorageDir(dir);\n} catch (FileAlreadyExistsException e) {\n    log.info(\"Directory {} already exists, skipping creation\", dir);\n}","preventionTips":["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"],"tags":["storage","obs","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-14T05:17:10.506Z"}