apache/cassandra · critical · FSWriteError

close( ) failed, errno ( ).

Error message

close(%d) failed, errno (%d).

What it means

NativeLibrary.tryCloseFD closes a native file descriptor; if close() fails and REQUIRE is set it logs and throws FSWriteError with the fd and errno. On POSIX systems a failed close can still indicate that previously buffered data was not durably written, so Cassandra treats it as a write error.

Solutions

  1. Fix double-close: ensure only one owner closes the fd (check getfd/channel lifecycle)
  2. Log the errno: EBADF points to premature or duplicate close in your code path; EIO points to disk trouble
  3. Audit native-fd management around file eviction and compaction for races; add ownership tracking
  4. If disk-related, follow the fsync-failure runbook: check dmesg, disk health, and run repair

Example fix

// before
int fd = NativeLibrary.getfd(channel);
channel.close();
NativeLibrary.tryCloseFD(fd); // EBADF: channel.close() already closed the fd
// after
int fd = NativeLibrary.getfd(channel);
NativeLibrary.tryCloseFD(fd);
channel.close();
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure the fd is still valid before closing: fcntl(fd, F_GETFD) != -1 via your native bridge

Try / catch

try { NativeLibrary.tryCloseFD(fd); } catch (FSWriteError e) { logger.warn("close failed for fd {}: {}", fd, e.getMessage()); /* investigate double-close or disk error */ }

Prevention

When it happens

Trigger: Calling tryCloseFD(fd) when the descriptor is already invalid (EBADF), was closed concurrently by another thread, or the kernel reports an I/O error while flushing on close.

Common situations: Double-close bugs (fd closed by FileChannel and then again via native path), threaded code closing the same descriptor, EINTR conditions, or underlying storage errors at close time.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/de72e34f3b40fe5a. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/utils/NativeLibrary.java:374

        try
        {
            wrappedLibrary.callClose(fd);
        }
        catch (UnsatisfiedLinkError e)
        {
            // JNA is unavailable just skipping Direct I/O
        }
        catch (RuntimeException e)
        {
            if (!(e instanceof LastErrorException))
                throw e;

            if (REQUIRE)
            {
                String errMsg = String.format("close(%d) failed, errno (%d).", fd, errno(e));
                logger.warn(errMsg);
                throw new FSWriteError(e, errMsg);
            }
        }
    }

    public static int getfd(FileChannel channel)
    {
        try
        {
            return getfd((FileDescriptor)FILE_CHANNEL_FD_FIELD.get(channel));
        }
        catch (IllegalArgumentException|IllegalAccessException e)
        {
            if (REQUIRE)
                logger.warn("Unable to read fd field from FileChannel", e);
        }
        return -1;
    }

View on GitHub (pinned to 88fd0f6a0e)