alibaba/arthas · error · IOException

Directory '{}' could not be created

Error message

Directory '{}' could not be created

What it means

FileUtils.openOutputStream() throws this IOException when the target file does not exist, a parent directory is specified, but parent.mkdirs() fails AND the parent is not already a directory. This covers the case where the parent path cannot be created — typically due to permissions or a conflicting non-directory entry.

Source

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

     * @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);
    }

    /**
     * save the command history to the given file, data will be overridden.
     * @param history the command history, each represented by an int array
     * @param file the file to save the history
     */
    public static void saveCommandHistory(List<int[]> history, File file) {
        try (OutputStream out = new BufferedOutputStream(openOutputStream(file, false))) {

View on GitHub (pinned to 21cf2e9ba5)

Solutions

  1. Manually create the parent directory beforehand and verify it exists: mkdir -p <parent>.
  2. Remove or rename any non-directory entry blocking the parent path.
  3. Verify the JVM process has write+execute permissions on the ancestor directories.
  4. Fix the configured path to avoid the conflicting component.

Example fix

// before: /tmp/arthas is a file, not a directory
File out = new File("/tmp/arthas/result.log");
FileUtils.openOutputStream(out, false); // throws 'Directory could not be created'

// after: remove conflicting entry, then write
// rm /tmp/arthas  (it was a file)
File out = new File("/tmp/arthas/result.log");
out.getParentFile().mkdirs();
FileUtils.openOutputStream(out, false);
Defensive patterns

Strategy: validation

Validate before calling

File file = new File(outputPath);
File parent = file.getParentFile();
if (parent != null && !parent.exists() && !parent.mkdirs()) {
    throw new IllegalStateException("Cannot create parent dir: " + parent);
}
FileUtils.openOutputStream(file, append);

Try / catch

try {
    FileUtils.openOutputStream(file, append);
} catch (IOException e) {
    if (e.getMessage().contains("could not be created")) {
        // resolve blocking entry or fix permissions, then retry
        File parent = file.getParentFile();
        if (parent.exists() && !parent.isDirectory()) parent.delete();
        parent.mkdirs();
        FileUtils.openOutputStream(file, append);
    } else { throw e; }
}

Prevention

When it happens

Trigger: Calling openOutputStream(file, append) where the file does not exist, file.getParentFile() is non-null, and parent.mkdirs() returns false while parent.isDirectory() is also false.

Common situations: The parent path collides with an existing file (e.g. /tmp/output exists as a file but /tmp/output/result.log is requested); insufficient permissions to create directories; a component of the parent path is a read-only mount; typo in the configured directory path.

Related errors


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