HMCL-dev/HMCL · warning · IOException
Failed to close session lock channel of the world
Error message
Failed to close session lock channel of the world
What it means
WorldManageUIUtils.closeSessionLockChannel closes a world's session.lock FileChannel and wraps any IOException from close() in a new IOException prefixed with "Failed to close session lock channel of the world ". Note the message string concatenates world.getFile() (the path) even though the log line uses getFileName(). It indicates the lock channel could not be released, which usually means the OS-level close failed.
Solutions
- Retry the delete/export operation after ensuring no other process (game, editor, sync client) is touching the world folder
- Check the chained cause (e.getCause()) to identify the real OS/filesystem error
- If developing, log-and-continue may be acceptable since close() failures are often benign — consider not failing the whole operation
- Run disk/antivirus exclusion checks on the .minecraft/saves directory
Example fix
// before
throw new IOException("Failed to close session lock channel of the world " + world.getFile(), e);
// after
try {
sessionLockChannel.close();
} catch (IOException e) {
LOG.warning("Failed to close session lock channel of the world " + world.getFile(), e);
// non-fatal: proceed with delete/export
} Defensive patterns
Strategy: try-catch
Validate before calling
// before delete/export
if (Files.exists(worldDir.resolve("session.lock"))) {
try (FileChannel ignored = FileChannel.open(worldDir.resolve("session.lock"), WRITE, CREATE_NEW)) {
// if this succeeds no other process holds an OS lock
} catch (IOException e) {
throw new IllegalStateException("World in use by another process");
}
} Try / catch
try {
WorldManageUIUtils.delete(world);
} catch (IOException e) {
if (e.getMessage().startsWith("Failed to close session lock channel")) {
LOG.warning("Non-fatal lock close failure", e); // proceed or retry
} else throw e;
} Prevention
- Close the game and world-editing tools before deleting/exporting worlds
- Exclude .minecraft/saves from antivirus real-time scanning and cloud sync
- Treat close() failures on lock channels as non-fatal and log them instead of aborting
When it happens
Trigger: Called from World deletion or export flows after getSessionLockChannel opened a session.lock file; the FileChannel.close() call throws IOException (e.g. the underlying file descriptor is in a bad state or the filesystem errors on close).
Common situations: Deleting/exporting a Minecraft world on Windows while another process holds the lock; antivirus or backup software interfering with file handles; network or FAT/exFAT filesystems with flaky close semantics; a previous double-close leaving the channel invalid.
Understand the failure class
Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.
Related errors
- Too many attempts
- "Mod " + modFile + " `mcmod.info` is malformed"
- "File " + modFile + " is not a LiteLoader mod."
- "File " + modFile + " is not a Quilt mod."
- The world has been locked
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/01a473d522ac78fa.
Report an issue: GitHub.
Appendix: source
Thrown at HMCL/src/main/java/org/jackhuang/hmcl/ui/instances/WorldManageUIUtils.java:127
).whenComplete(Schedulers.javafx(), (throwable) -> {
if (throwable == null) {
handler.resolve();
} else {
handler.reject(i18n("world.duplicate.failed"));
LOG.warning("Failed to duplicate world " + world.getFile(), throwable);
}
})
.start();
}, "", new RequiredValidator(), new Validator(i18n("world.duplicate.failed.invalid_name"), FileUtils::isNameValid));
}
public static void closeSessionLockChannel(World world, FileChannel sessionLockChannel) throws IOException {
if (sessionLockChannel != null) {
try {
sessionLockChannel.close();
LOG.info("Closed session lock channel of the world " + world.getFileName());
} catch (IOException e) {
throw new IOException("Failed to close session lock channel of the world " + world.getFile(), e);
}
}
}
public static FileChannel getSessionLockChannel(World world) {
try {
FileChannel lock = world.lock();
LOG.info("Acquired lock on world " + world.getFileName());
return lock;
} catch (WorldLockedException ignored) {
return null;
}
}
}
View on GitHub (pinned to 24702dc5a0)