HMCL-dev/HMCL · error
Destination ' ' exists but is read-only
Error message
Destination '<destFile>' exists but is read-only
What it means
Guard in FileUtils.copyFile: the destination file already exists but is not writable, so the REPLACE_EXISTING copy would fail; the method rejects it up front with an IOException naming destFile. Generic pre-condition validation of the destination argument.
Solutions
- Close the process holding/using the destination file (e.g. running Minecraft)
- Clear the read-only flag or fix permissions (chmod +w / file Properties > uncheck Read-only)
- Delete the read-only destination first, then copy
- Run the launcher with sufficient privileges or copy to a user-writable location
Example fix
// before FileUtils.copyFile(src, dest); // after if (Files.exists(dest) && !Files.isWritable(dest)) dest.toFile().setWritable(true); FileUtils.copyFile(src, dest);
Defensive patterns
Strategy: try-catch
Validate before calling
if (Files.exists(destFile) && !Files.isWritable(destFile))
throw new AccessDeniedException(destFile.toString()); Try / catch
try {
FileUtils.copyFile(src, dest);
} catch (IOException e) {
if (e.getMessage().contains("read-only")) {
// prompt user to close the game / fix permissions, then retry
} else throw e;
} Prevention
- Ensure the game/launcher is not running when updating files it holds
- Check Files.isWritable on destinations before overwriting
- Avoid installing into admin-protected directories (Program Files, /usr)
- Handle Windows read-only attributes after crashes or installers
When it happens
Trigger: Calling FileUtils.copyFile when destFile already exists and its permission bits (or file locks/ownership on Windows) prevent writing.
Common situations: Overwriting game files locked by a running instance of the game/launcher; files left read-only by a previous crash or installer; copying into system-protected directories without admin rights.
Understand the failure class
Background: "Permission denied" / "Failed to write" file errors: why a library can't write its files to disk (EACCES, EPERM, ENOSPC) and how to fix them — this error's family across 43 libraries.
Related errors
- Source ' ' does not exist
- Source ' ' exists but is a directory
- Asset index file malformed
- Bad exit code
- Cannot export a background directory as a theme-pack asset
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/6ba0ed19f6f274df.
Report an issue: GitHub.
Appendix: source
Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/FileUtils.java:481
public static void copyFile(Path srcFile, Path destFile)
throws IOException {
Objects.requireNonNull(srcFile, "Source must not be null");
Objects.requireNonNull(destFile, "Destination must not be null");
if (!Files.exists(srcFile))
throw new FileNotFoundException("Source '" + srcFile + "' does not exist");
if (Files.isDirectory(srcFile))
throw new IOException("Source '" + srcFile + "' exists but is a directory");
Files.createDirectories(destFile.getParent());
if (Files.exists(destFile) && !Files.isWritable(destFile))
throw new IOException("Destination '" + destFile + "' exists but is read-only");
Files.copy(srcFile, destFile, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING);
}View on GitHub (pinned to 24702dc5a0)