alibaba/arthas · error · IOException

File '{file}' cannot be written to

Error message

File '{file}' cannot be written to

What it means

FileUtils.openOutputStream(file, append): when the target exists, is not a directory, but file.canWrite() is false, it throws IOException("File '<file>' cannot be written to"). The existing file is present but not writable by the current process.

Source

Thrown at common/src/main/java/com/taobao/arthas/common/FileUtils.java:119

	 * 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(final File file, final 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 {
			final 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);
	}
	
    /**
     * Reads the contents of a file into a byte array.
     * The file is always closed.
     *
     * @param file the file to read, must not be {@code null}
     * @return the file contents, never {@code null}

View on GitHub (pinned to 21cf2e9ba5)

Solutions

  1. Fix permissions: chmod u+w <file> or chown to the running user.
  2. Run the Arthas/agent process under a user that owns the file.
  3. Remove immutable attribute if set (chattr -i).
  4. Point output at a writable location instead.

Example fix

# before
# file owned by root, process runs as app user
FileUtils.openOutputStream(new File("/var/log/arthas.log"), true);  // throws

# after
chown app:app /var/log/arthas.log && chmod u+w /var/log/arthas.log
Defensive patterns

Strategy: validation

Validate before calling

if (file.exists() && file.isFile() && !file.canWrite()) {
    throw new IOException("file not writable: " + file);
}

Type guard

static boolean isWritable(File f) {
    return f != null && (!f.exists() || f.canWrite());
}

Try / catch

try {
    return FileUtils.openOutputStream(file, append);
} catch (IOException e) {
    if (e.getMessage().contains("cannot be written to")) {
        // fix ownership/permissions, then retry
    } else throw e;
}

Prevention

When it happens

Trigger: Opening an existing file for output when the process lacks write permission on it (read-only file, owned by another user, immutable attribute set).

Common situations: File created by a different user/service and not chowned; container uid mismatch vs host file ownership; file marked read-only or immutable (chattr +i); SELinux/AppArmor denying writes.

Related errors


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