{"record":{"id":"3b95fe204d591ad4","repo":"shadow1ng/fscan","slug":"failed-to-create-csv-file-w","errorCode":null,"errorMessage":"failed to create CSV file: %w","messagePattern":"failed to create CSV file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/output/writers.go","lineNumber":612,"sourceCode":"\n// CSVWriter CSV格式写入器（分类去重）\n// 双写机制：内存分类缓冲 + 实时NDJSON备份\ntype CSVWriter struct {\n\tfile         *os.File\n\tbufWriter    *bufio.Writer\n\tcsvWriter    *csv.Writer\n\tmu           sync.Mutex\n\tclosed       bool\n\tbuffer       *ResultBuffer\n\trealtimeFile *os.File // 实时备份文件（NDJSON格式）\n\trealtimePath string   // 实时备份文件路径\n}\n\n// NewCSVWriter 创建CSV写入器\nfunc NewCSVWriter(filePath string) (*CSVWriter, error) {\n\tfile, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, DefaultFilePermissions)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create CSV file: %w\", err)\n\t}\n\n\t// 创建实时备份文件（NDJSON格式）\n\trealtimePath := filePath + \".realtime.tmp\"\n\trealtimeFile, err := os.OpenFile(realtimePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, DefaultFilePermissions)\n\tif err != nil {\n\t\tfile.Close()\n\t\treturn nil, fmt.Errorf(\"failed to create realtime backup file: %w\", err)\n\t}\n\n\tbufWriter := bufio.NewWriter(file)\n\tcsvWriter := csv.NewWriter(bufWriter)\n\n\treturn &CSVWriter{\n\t\tfile:         file,\n\t\tbufWriter:    bufWriter,\n\t\tcsvWriter:    csvWriter,\n\t\tbuffer:       NewResultBuffer(),","sourceCodeStart":594,"sourceCodeEnd":630,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/common/output/writers.go#L594-L630","documentation":"NewCSVWriter creates (truncating) the main CSV output file; this error is returned when os.OpenFile fails. The constructor aborts and returns the wrapped OS error, since a CSV writer cannot function without its output file.","triggerScenarios":"os.OpenFile(filePath, O_CREATE|O_WRONLY|O_TRUNC) fails: parent directory missing, no write permission, filePath is an existing directory, or fd limit exhausted.","commonSituations":"Output path configured as a directory or pointing at a nonexistent folder; running as a user without permission on the output directory; path typos; read-only container volume.","solutions":["Create the parent directory first with os.MkdirAll(filepath.Dir(filePath), 0o755)","Verify filePath is a valid writable file path, not a directory","Check filesystem permissions for the running user","Inspect the wrapped error (ENOENT/EACCES/ENOSPC) for the specific cause","Check ulimit -n if the process holds many open files"],"exampleFix":"// before\nw, err := output.NewCSVWriter(cfg.OutputPath)\n// after\nif err := os.MkdirAll(filepath.Dir(cfg.OutputPath), 0o755); err != nil {\n\treturn err\n}\nw, err := output.NewCSVWriter(cfg.OutputPath)","handlingStrategy":"validation","validationCode":"if err := os.MkdirAll(filepath.Dir(filePath), 0o755); err != nil { return err }\nif fi, err := os.Stat(filePath); err == nil && fi.IsDir() { return fmt.Errorf(\"CSV path is a directory: %s\", filePath) }\nprobe, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY, 0o644)\nif err != nil { return err }\nprobe.Close()","typeGuard":null,"tryCatchPattern":"w, err := output.NewCSVWriter(path)\nif err != nil {\n\tvar pe *fs.PathError\n\tif errors.As(err, &pe) {\n\t\tif errors.Is(pe.Err, syscall.ENOENT) { os.MkdirAll(filepath.Dir(path), 0o755) }\n\t\tif errors.Is(pe.Err, syscall.EACCES) { return fmt.Errorf(\"check permissions on %s\", pe.Path) }\n\t}\n\treturn err\n}","preventionTips":["Create output directories at startup before constructing writers","Validate CSV output paths in config (exists, writable, not a directory)","Run under a user with write access to the output location","Pre-flight probe writes before starting long scans","Monitor fd usage to stay under the open-file limit"],"tags":["go","file-io","csv","initialization"],"backgroundTag":"file-open-failed","analyzedSha":"95cc12e753bf43de7004e5aef42a9ffba3934303","analyzedAt":"2026-09-06T17:07:30.094Z","contentChangedAt":"2026-09-06T17:07:30.094Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}