HMCL-dev/HMCL · error
Source ' ' exists but is a directory
Error message
Source '<srcFile>' exists but is a directory
What it means
Guard in FileUtils.copyFile: the source path exists but is a directory. copyFile only copies regular files; callers must use a directory-copy routine instead. Generic pre-condition validation of the srcFile argument.
Solutions
- Pass the full path to the individual file, not its containing directory
- Check Files.isDirectory(srcFile) beforehand and use a recursive copy utility for directories
- Correct the configuration/variable that holds the wrong path
Example fix
// before
FileUtils.copyFile(modsDir, backupDir.resolve("mods"));
// after
for (Path f : FileUtils.listFilesByExtension(modsDir, ".jar"))
FileUtils.copyFile(f, backupDir.resolve(modsDir.relativize(f))); Defensive patterns
Strategy: validation
Validate before calling
if (Files.isDirectory(srcFile))
throw new IllegalArgumentException("expected a file, got directory: " + srcFile); Type guard
static boolean isRegularFileOrNull(Path p) { return p != null && Files.isRegularFile(p) && !Files.isDirectory(p); } Try / catch
try {
FileUtils.copyFile(src, dest);
} catch (IOException e) {
if (e.getMessage().contains("is a directory")) {
// switch to a recursive directory copy
} else throw e;
} Prevention
- Point copy operations at concrete files, never directories
- Validate user-selected paths (file vs directory choosers)
- Use a recursive copy helper when directory semantics are needed
When it happens
Trigger: Passing a directory path (e.g. the .minecraft folder itself, or a folder expected to contain the file) as srcFile to FileUtils.copyFile.
Common situations: Config errors pointing at a directory instead of a file (e.g. 'assets/' vs 'assets/index.json'); user-selected folders fed to a file-copy API; a path that changed from file to directory between versions.
Related errors
- Source ' ' does not exist
- Destination ' ' exists but is read-only
- 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/f4e774e07a90e22a.
Report an issue: GitHub.
Appendix: source
Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/FileUtils.java:478
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)