alibaba/arthas · error · IOException

File '{}' cannot be written to

Error message

File '{}' cannot be written to

What it means

FileUtils.openOutputStream() throws this IOException when the target File exists and is a regular file but is not writable by the current process. This is a permission/ownership check before attempting to construct the FileOutputStream.

Source

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

     * 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. Check and fix file permissions: chmod u+w <file> or chown to the JVM user.
  2. If running in a container, ensure the mounted volume is writable by the container user.
  3. Redirect output to a writable directory/file (e.g. under /tmp or a designated writable path).
  4. Remove the stale read-only file so openOutputStream can recreate it.

Example fix

// before: file owned by root, JVM runs as appuser
File out = new File("/var/log/arthas.log");
FileUtils.openOutputStream(out, true); // throws 'cannot be written to'

// after: use a writable location
File out = new File(System.getProperty("java.io.tmpdir"), "arthas.log");
FileUtils.openOutputStream(out, true);
Defensive patterns

Strategy: validation

Validate before calling

File file = new File(outputPath);
if (file.exists() && !file.canWrite()) {
    throw new IllegalStateException("File not writable: " + file + " — check permissions");
}
FileUtils.openOutputStream(file, append);

Try / catch

try {
    FileUtils.openOutputStream(file, append);
} catch (IOException e) {
    if (e.getMessage().contains("cannot be written")) {
        file = new File(System.getProperty("java.io.tmpdir"), "arthas-output.log");
        FileUtils.openOutputStream(file, append);
    } else { throw e; }
}

Prevention

When it happens

Trigger: Calling openOutputStream(file, append) where file.exists() is true, file.isDirectory() is false, but file.canWrite() returns false.

Common situations: The output file is owned by another user and lacks world/group write permission; the file is on a read-only filesystem; the JVM process runs as a different user than the file owner; a previous run created the file as root and the current run is non-root.

Related errors


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