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
- Fix permissions: chmod u+w <file> or chown to the running user.
- Run the Arthas/agent process under a user that owns the file.
- Remove immutable attribute if set (chattr -i).
- 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
- Run the process under a user that owns (or can write) the output file.
- chmod u+w output files; remove immutable attributes.
- In containers, match the uid to the host file owner.
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
- Directory '{parent}' could not be created
- File '{file}' exists but is a directory
- Bad zip entry: {currentEntry}
- Failed to create directory within ${TEMP_DIR_ATTEMPTS} attem
- Failed to prepare MCP upload directory
AI-assisted analysis of alibaba/arthas@21cf2e9ba5 (2026-08-14).
Data as JSON: /api/errors/b7e476345b722460.
Report an issue: GitHub.