elastic/elasticsearch · error · NoSuchFileException
{}
Error message
{} What it means
Thrown as a NoSuchFileException by IOUtils.fsync when, on Windows, the caller asserts isDir=true but the directory does not exist. Windows cannot open a directory for fsync, so the method short-circuits — but not before verifying the directory exists, since silently ignoring a missing directory would hide real bugs. For non-existent regular files the channel open will fail with the standard NoSuchFileException from the filesystem.
Source
Thrown at libs/core/src/main/java/org/elasticsearch/core/IOUtils.java:293
}
/**
* Ensure that any writes to the given file is written to the storage device that contains it. The {@code isDir} parameter specifies
* whether or not the path to sync is a directory. This is needed because we open for read and ignore an {@link IOException} since not
* all filesystems and operating systems support fsyncing on a directory. For regular files we must open for write for the fsync to have
* an effect.
*
* @param fileToSync the file to fsync
* @param isDir if true, the given file is a directory (we open for read and ignore {@link IOException}s, because not all file
* systems and operating systems allow to fsync on a directory)
* @param metaData if {@code true} both the file's content and metadata will be sync, otherwise only the file's content will be sync
*/
public static void fsync(final Path fileToSync, final boolean isDir, final boolean metaData) throws IOException {
if (isDir && WINDOWS) {
// opening a directory on Windows fails, directories can not be fsynced there
if (Files.exists(fileToSync) == false) {
// yet do not suppress trying to fsync directories that do not exist
throw new NoSuchFileException(fileToSync.toString());
}
return;
}
try (FileChannel file = FileChannel.open(fileToSync, isDir ? StandardOpenOption.READ : StandardOpenOption.WRITE)) {
try {
file.force(metaData);
} catch (final IOException e) {
if (isDir) {
assert (LINUX || MAC_OS_X) == false
: "on Linux and MacOSX fsyncing a directory should not throw IOException, "
+ "we just don't want to rely on that in production (undocumented); got: "
+ e;
// ignore exception if it is a directory
return;
}
// throw original exception
throw e;
}View on GitHub (pinned to db6a809a66)
Solutions
- Ensure the directory exists before fsyncing it (create it with Files.createDirectories first).
- If the directory is optional, check Files.exists(path) before calling and skip when absent — but only if that is semantically safe.
- On the recovery path, order operations so the directory is created before the first fsync.
- Investigate concurrent deletion: a missing directory mid-recovery often indicates a race with cleanup.
Example fix
// before IOUtils.fsync(dir, true); // throws if dir absent // after Files.createDirectories(dir); IOUtils.fsync(dir, true);
Defensive patterns
Strategy: validation
Validate before calling
// Ensure a directory exists before fsyncing it
static void fsyncDir(Path dir) throws IOException {
if (!Files.exists(dir)) Files.createDirectories(dir);
IOUtils.fsync(dir, true);
} Type guard
static boolean isFsyncableDir(Path dir) {
return Files.isDirectory(dir); // implies exists
} Try / catch
try {
IOUtils.fsync(dir, true);
} catch (NoSuchFileException e) {
// create and retry once; if still failing, surface as a recovery error
Files.createDirectories(dir);
IOUtils.fsync(dir, true);
} Prevention
- Create directories with Files.createDirectories before the first fsync.
- Order recovery paths so directory creation precedes fsync.
- On Windows CI, test the missing-directory case explicitly.
- If a directory may legitimately be absent, guard with Files.exists before fsync.
When it happens
Trigger: Calling IOUtils.fsync(path, true /*isDir*/, ...) on Windows where `path` does not exist or was deleted before the call. Also reachable when isDir=false and the file does not exist (via FileChannel.open throwing NoSuchFileException).
Common situations: A shutdown/recovery path that fsyncs a data directory after it was concurrently removed. Test cleanup racing with a durability flush. A configurable path that the user pointed at a non-existent directory. Windows-only CI exposing a bug hidden on Linux, where directory fsync exceptions are swallowed.
Related errors
- could not remove the following files (in the order of attemp
- Unable to create reaper JAR output directory {}
- Failed to write unicast_hosts for {}
- Failed to create working directory for {}, with: {}
- Can't create extra config file for
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/23e529859bc67bd8.
Report an issue: GitHub.