alibaba/arthas · error · IOException

File '{}' exists but is a directory

Error message

File '{}' exists but is a directory

What it means

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.

Source

Thrown at core/src/main/java/com/taobao/arthas/core/util/FileUtils.java:77

     * The parent directory will be created if it does not exist.
     * The file will be created if it does not exist.
     * An exception is thrown if the file object exists but is a directory.
     * An exception is thrown if the file exists but cannot be written to.
     * An exception is thrown if the parent directory cannot be created.
     *
     * @param file  the file to open for output, must not be {@code null}
     * @param append if {@code true}, then bytes will be added to the
     * end of the file rather than overwriting
     * @return a new {@link FileOutputStream} for the specified file
     * @throws IOException if the file object is a directory
     * @throws IOException if the file cannot be written to
     * @throws IOException if a parent directory needs creating but that fails
     * @since 2.1
     */
    public static FileOutputStream openOutputStream(File file, boolean append) throws IOException {
        if (file.exists()) {
            if (file.isDirectory()) {
                throw new IOException("File '" + file + "' exists but is a directory");
            }
            if (!file.canWrite()) {
                throw new IOException("File '" + file + "' cannot be written to");
            }
        } else {
            File parent = file.getParentFile();
            if (parent != null) {
                if (!parent.mkdirs() && !parent.isDirectory()) {
                    throw new IOException("Directory '" + parent + "' could not be created");
                }
            }
        }
        return new FileOutputStream(file, append);
    }

    private static boolean isAuthCommand(String command) {
        // 需要改写 auth command, TODO 更准确应该是用mask去掉密码信息
        return command != null && command.trim().startsWith(ArthasConstants.AUTH);

View on GitHub (pinned to 21cf2e9ba5)

Solutions

  1. Change the configured output file path to point at a file name, not a directory path (append a filename component).
  2. If a directory was accidentally created at that path, remove or rename it before retrying.
  3. Add a pre-check in caller code: if (file.isDirectory()) choose a different file path.

Example fix

// before
File out = new File("/tmp/arthas-out"); // /tmp/arthas-out is a directory
FileUtils.openOutputStream(out, false);

// after
File out = new File("/tmp/arthas-out/result.log");
FileUtils.openOutputStream(out, false);
Defensive patterns

Strategy: validation

Validate before calling

File file = new File(outputPath);
if (file.isDirectory()) {
    throw new IllegalArgumentException("Output path is a directory, specify a file: " + outputPath);
}
FileUtils.openOutputStream(file, append);

Try / catch

try {
    FileUtils.openOutputStream(file, append);
} catch (IOException e) {
    if (e.getMessage().contains("is a directory")) {
        file = new File(file, "output.log"); // append filename
        FileUtils.openOutputStream(file, append);
    } else { throw e; }
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of alibaba/arthas@21cf2e9ba5 (2026-08-14). Data as JSON: /api/errors/e13d562954b5a9a8. Report an issue: GitHub.