{"record":{"id":"e13d562954b5a9a8","repo":"alibaba/arthas","slug":"file-exists-but-is-a-directory","errorCode":null,"errorMessage":"File '{}' exists but is a directory","messagePattern":"File '(.+?)' exists but is a directory","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/com/taobao/arthas/core/util/FileUtils.java","lineNumber":77,"sourceCode":"     * The parent directory will be created if it does not exist.\n     * The file will be created if it does not exist.\n     * An exception is thrown if the file object exists but is a directory.\n     * An exception is thrown if the file exists but cannot be written to.\n     * An exception is thrown if the parent directory cannot be created.\n     *\n     * @param file  the file to open for output, must not be {@code null}\n     * @param append if {@code true}, then bytes will be added to the\n     * end of the file rather than overwriting\n     * @return a new {@link FileOutputStream} for the specified file\n     * @throws IOException if the file object is a directory\n     * @throws IOException if the file cannot be written to\n     * @throws IOException if a parent directory needs creating but that fails\n     * @since 2.1\n     */\n    public static FileOutputStream openOutputStream(File file, boolean append) throws IOException {\n        if (file.exists()) {\n            if (file.isDirectory()) {\n                throw new IOException(\"File '\" + file + \"' exists but is a directory\");\n            }\n            if (!file.canWrite()) {\n                throw new IOException(\"File '\" + file + \"' cannot be written to\");\n            }\n        } else {\n            File parent = file.getParentFile();\n            if (parent != null) {\n                if (!parent.mkdirs() && !parent.isDirectory()) {\n                    throw new IOException(\"Directory '\" + parent + \"' could not be created\");\n                }\n            }\n        }\n        return new FileOutputStream(file, append);\n    }\n\n    private static boolean isAuthCommand(String command) {\n        // 需要改写 auth command, TODO 更准确应该是用mask去掉密码信息\n        return command != null && command.trim().startsWith(ArthasConstants.AUTH);","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/alibaba/arthas/blob/21cf2e9ba52b305290be7223b980ff504bb9cb5b/core/src/main/java/com/taobao/arthas/core/util/FileUtils.java#L59-L95","documentation":"FileUtils.openOutputStream() throws this IOException when the target File already exists and is a directory rather than a regular file. The method is a thin pre-check wrapper around FileOutputStream and refuses to open a directory for writing because FileOutputStream would fail with a less descriptive error.","triggerScenarios":"Calling openOutputStream(file, append) where file resolves to an existing directory path (e.g. file = new File(\"/tmp/somedir\") and that path is a directory).","commonSituations":"An output path was configured to a directory instead of a file path (e.g. arthas output file set to /tmp/ instead of /tmp/arthas-output.log); a parent directory and the output file share the same name; stale directory left over from a prior run at the target path.","solutions":["Change the configured output file path to point at a file name, not a directory path (append a filename component).","If a directory was accidentally created at that path, remove or rename it before retrying.","Add a pre-check in caller code: if (file.isDirectory()) choose a different file path."],"exampleFix":"// before\nFile out = new File(\"/tmp/arthas-out\"); // /tmp/arthas-out is a directory\nFileUtils.openOutputStream(out, false);\n\n// after\nFile out = new File(\"/tmp/arthas-out/result.log\");\nFileUtils.openOutputStream(out, false);","handlingStrategy":"validation","validationCode":"File file = new File(outputPath);\nif (file.isDirectory()) {\n    throw new IllegalArgumentException(\"Output path is a directory, specify a file: \" + outputPath);\n}\nFileUtils.openOutputStream(file, append);","typeGuard":null,"tryCatchPattern":"try {\n    FileUtils.openOutputStream(file, append);\n} catch (IOException e) {\n    if (e.getMessage().contains(\"is a directory\")) {\n        file = new File(file, \"output.log\"); // append filename\n        FileUtils.openOutputStream(file, append);\n    } else { throw e; }\n}","preventionTips":["Always end configured output paths with a filename component, not a trailing slash.","Validate the output path with file.isDirectory() before opening for write."],"tags":["arthas","file-io","filesystem","configuration"],"backgroundTag":null,"analyzedSha":"21cf2e9ba52b305290be7223b980ff504bb9cb5b","analyzedAt":"2026-08-14T00:57:07.243Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}