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

  1. Ensure the directory exists before fsyncing it (create it with Files.createDirectories first).
  2. If the directory is optional, check Files.exists(path) before calling and skip when absent — but only if that is semantically safe.
  3. On the recovery path, order operations so the directory is created before the first fsync.
  4. 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

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


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/23e529859bc67bd8. Report an issue: GitHub.