{"record":{"id":"25b97e31fc624160","repo":"crowdsecurity/crowdsec","slug":"unable-to-close-s-s","errorCode":null,"errorMessage":"unable to close %s : %s","messagePattern":"unable to close (.+?) : (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/acquisition/modules/file/run.go","lineNumber":217,"sourceCode":"\ts.tailMapMutex.RLock()\n\n\tif s.tails[file] {\n\t\ts.tailMapMutex.RUnlock()\n\t\tlogger.Debugf(\"Already tailing file %s, not creating a new tail\", file)\n\n\t\treturn nil\n\t}\n\n\ts.tailMapMutex.RUnlock()\n\n\t// Validate file\n\tfd, err := os.Open(file)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to read %s : %s\", file, err)\n\t}\n\n\tif err = fd.Close(); err != nil {\n\t\treturn fmt.Errorf(\"unable to close %s : %s\", file, err)\n\t}\n\n\tfi, err := os.Stat(file)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"could not stat file %s : %w\", file, err)\n\t}\n\n\tif fi.IsDir() {\n\t\tlogger.Warnf(\"%s is a directory, ignoring it.\", file)\n\t\treturn nil\n\t}\n\n\t// Determine polling mode\n\tpollFile := false\n\tif s.config.PollWithoutInotify != nil {\n\t\tpollFile = *s.config.PollWithoutInotify\n\t} else {\n\t\tnetworkFS, fsType, err := fsutil.IsNetworkFS(file)","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/acquisition/modules/file/run.go#L199-L235","documentation":"After successfully opening the file to validate readability, setupTailForFile immediately closes it. If fd.Close() fails, the module returns \"unable to close %s : %s\". This is rare: it signals the file descriptor could not be released, usually due to filesystem errors or resource exhaustion.","triggerScenarios":"os.Open succeeded but fd.Close() returned an error inside setupTailForFile (called by StreamingAcquisition or checkAndTailFile).","commonSituations":"Filesystem I/O errors (NFS stale handles, disk issues); process hitting file-descriptor limits in exotic setups; interrupted syscalls on flaky storage.","solutions":["Check the underlying OS error in the log (e.g. 'input/output error', 'device or resource busy').","Check filesystem health (dmesg, df, mount state) if on NFS or network storage.","Check open file descriptor limits (ulimit -n) and raise if the process is leaking descriptors.","Restart crowdsec to clear any stuck descriptors and retry."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// inspect the wrapped OS error\nif err := setupTailForFile(...); err != nil {\n    log.Printf(\"tail setup failed: %v\", err) // surfaces the close() cause\n}","preventionTips":["Monitor filesystem health on hosts running crowdsec (especially NFS).","Watch open FD counts per process to avoid descriptor exhaustion.","Treat repeated close failures as a storage problem, not an acquisition problem."],"tags":["file-io","acquisition","go","filesystem"],"backgroundTag":"file-close-failed","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}