{"record":{"id":"de72e34f3b40fe5a","repo":"apache/cassandra","slug":"close-d-failed-errno-d","errorCode":null,"errorMessage":"close(%d) failed, errno (%d).","messagePattern":"close\\((.+?)\\) failed, errno \\((.+?)\\)\\.","errorType":"exception","errorClass":"FSWriteError","httpStatus":null,"severity":"critical","filePath":"src/java/org/apache/cassandra/utils/NativeLibrary.java","lineNumber":374,"sourceCode":"\n        try\n        {\n            wrappedLibrary.callClose(fd);\n        }\n        catch (UnsatisfiedLinkError e)\n        {\n            // JNA is unavailable just skipping Direct I/O\n        }\n        catch (RuntimeException e)\n        {\n            if (!(e instanceof LastErrorException))\n                throw e;\n\n            if (REQUIRE)\n            {\n                String errMsg = String.format(\"close(%d) failed, errno (%d).\", fd, errno(e));\n                logger.warn(errMsg);\n                throw new FSWriteError(e, errMsg);\n            }\n        }\n    }\n\n    public static int getfd(FileChannel channel)\n    {\n        try\n        {\n            return getfd((FileDescriptor)FILE_CHANNEL_FD_FIELD.get(channel));\n        }\n        catch (IllegalArgumentException|IllegalAccessException e)\n        {\n            if (REQUIRE)\n                logger.warn(\"Unable to read fd field from FileChannel\", e);\n        }\n        return -1;\n    }\n","sourceCodeStart":356,"sourceCodeEnd":392,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/utils/NativeLibrary.java#L356-L392","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Fix double-close: ensure only one owner closes the fd (check getfd/channel lifecycle)","Log the errno: EBADF points to premature or duplicate close in your code path; EIO points to disk trouble","Audit native-fd management around file eviction and compaction for races; add ownership tracking","If disk-related, follow the fsync-failure runbook: check dmesg, disk health, and run repair"],"exampleFix":"// before\nint fd = NativeLibrary.getfd(channel);\nchannel.close();\nNativeLibrary.tryCloseFD(fd); // EBADF: channel.close() already closed the fd\n// after\nint fd = NativeLibrary.getfd(channel);\nNativeLibrary.tryCloseFD(fd);\nchannel.close();","handlingStrategy":"try-catch","validationCode":"// ensure the fd is still valid before closing: fcntl(fd, F_GETFD) != -1 via your native bridge","typeGuard":null,"tryCatchPattern":"try { NativeLibrary.tryCloseFD(fd); } catch (FSWriteError e) { logger.warn(\"close failed for fd {}: {}\", fd, e.getMessage()); /* investigate double-close or disk error */ }","preventionTips":["Give each fd a single owner responsible for closing","Never close both via FileChannel and native fd","Log fd acquisition/close pairs to spot duplicate closes","Treat repeated EBADF on close as a code bug, not a disk problem"],"tags":["file-descriptor","close","fs-write-error","native"],"backgroundTag":"file-write-failed","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}