alibaba/arthas · error · IOException

${filePath}: Is a directory

Error message

${filePath}: Is a directory

What it means

The tee output handler (for '| tee <path>') refuses to open a path that is an existing directory, matching standard tee behavior. It throws IOException before attempting FileWriter creation.

Source

Thrown at core/src/main/java/com/taobao/arthas/core/shell/command/internal/TeeHandler.java:28

import java.io.*;
import java.util.List;

/**
 * @author min.yang
 */
public class TeeHandler extends StdoutHandler implements CloseFunction {
    public static final String NAME = "tee";
    private PrintWriter out;
    private static CLI cli = null;

    public TeeHandler(String filePath, boolean append) throws IOException {
        if (StringUtils.isEmpty(filePath)) {
            return;
        }
        File file = new File(filePath);

        if (file.isDirectory()) {
            throw new IOException(filePath + ": Is a directory");
        }

        if (!file.exists()) {
            File parentFile = file.getParentFile();
            if (parentFile != null) {
                parentFile.mkdirs();
            }
        }
        out = new PrintWriter(new BufferedWriter(new FileWriter(file, append)));
    }

    public static StdoutHandler inject(List<CliToken> tokens) {
        List<String> args = StdoutHandler.parseArgs(tokens, NAME);

        TeeCommand teeCommand = new TeeCommand();
        if (cli == null) {
            cli = CLIConfigurator.define(TeeCommand.class);
        }

View on GitHub (pinned to 21cf2e9ba5)

Solutions

  1. Specify a file path for the tee output.
  2. Append a filename to the directory path.
  3. Remove trailing slashes.

Example fix

// before (in Arthas shell)
thread | tee /tmp
// after
thread | tee /tmp/thread-dump.txt
Defensive patterns

Strategy: validation

Validate before calling

// Before constructing TeeHandler, check the target is not a directory
if (filePath != null && !filePath.isEmpty()) {
    File f = new File(filePath);
    if (f.isDirectory()) {
        throw new IOException(filePath + ": Is a directory — specify a file path");
    }
}

Try / catch

try {
    TeeHandler handler = new TeeHandler(filePath, append);
} catch (IOException e) {
    if (e.getMessage().endsWith(": Is a directory")) {
        // tee target is a directory — ask user for a file path
    }
}

Prevention

When it happens

Trigger: Using the tee pipe in an Arthas shell command (e.g., 'thread | tee /tmp') where the target path is an existing directory. Note: if filePath is empty the constructor silently returns without error (line 22-24).

Common situations: User specifies a directory path as the tee target; trailing slash; directory name collision; empty path is silently ignored so the error only fires for a non-empty directory path.

Related errors


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