{"record":{"id":"7aed3b759f27c580","repo":"moonD4rk/HackBrowserData","slug":"write-s-w","errorCode":null,"errorMessage":"write %s: %w","messagePattern":"write (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"output/output.go","lineNumber":165,"sourceCode":"\n\tf, err := os.OpenFile(filepath.Clean(path), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o600)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"create %s: %w\", filename, err)\n\t}\n\tdefer func() {\n\t\tif cerr := f.Close(); cerr != nil && err == nil {\n\t\t\terr = fmt.Errorf(\"close %s: %w\", filename, cerr)\n\t\t}\n\t}()\n\n\tif strings.HasSuffix(path, \".csv\") {\n\t\tif _, err := f.Write(utf8BOM); err != nil {\n\t\t\treturn fmt.Errorf(\"write BOM: %w\", err)\n\t\t}\n\t}\n\n\tif _, err := f.Write(buf.Bytes()); err != nil {\n\t\treturn fmt.Errorf(\"write %s: %w\", filename, err)\n\t}\n\treturn nil\n}\n","sourceCodeStart":147,"sourceCodeEnd":169,"githubUrl":"https://github.com/moonD4rk/HackBrowserData/blob/0503d04d7a8d0379d060268a74f1b149e5a0aad5/output/output.go#L147-L169","documentation":"This error wraps an OS-level failure that occurred while writing the formatted browser data buffer to an output file (e.g. password.csv, cookie.json) via f.Write(buf.Bytes()) in writeFile. The library opens the destination file itself and streams the aggregated rows to it; if the underlying write syscall fails (disk full, I/O error, file closed/invalid handle), the original error is wrapped with the target filename as context. It is distinct from the earlier 'create %s' error (which fires at os.OpenFile) and the 'write BOM' error (which fires only for CSV BOM bytes).","triggerScenarios":"Writer.Write() -> writeFile(category, rows): os.OpenFile succeeds but f.Write(buf.Bytes()) fails. Typical causes: disk full (ENOSPC), I/O error on the device (EIO), file opened on a read-only mount after creation succeeded via quirks, quota exceeded, or (rarely) a bad file descriptor if the deferred Close raced — though in this code the write happens before close, so it's almost always an OS/storage-level write failure. Not triggered by formatting errors (those return 'format %s') or empty buffers (no file is created).","commonSituations":"Running the tool against a full or nearly-full disk (common on small VPS or live-USB environments). Output directory on a failing/removable USB drive or network mount (SMB/NFS) that drops mid-write. Disk quota exceeded on shared hosting or university lab machines. Filesystem went read-only after a kernel detected errors (ext4 remount-ro). SELinux/AppArmor policies that allow file creation but block writes in certain contexts.","solutions":["Check free disk space on the output directory's filesystem (df -h <outdir>) and free space or redirect output to another disk with a larger capacity.","Verify the output directory is not on a read-only or failing filesystem: check `mount` for 'ro' flags or dmesg for I/O errors; move -o/--output to a healthy local path.","Check for disk quotas (quota -s or cloud-provider limits) and raise them or reduce output volume.","Rerun the command; transient I/O errors on network mounts may succeed on retry after the mount recovers.","If it persists, inspect the wrapped inner error (%w) in the message — it names the exact syscall errno — and address that specific cause (e.g. EDQUOT, ENOSPC, EIO)."],"exampleFix":"// before: letting Write fail mid-export with a raw wrapped OS error\nif err := w.Write(); err != nil {\n\tlog.Fatal(err) // \"write password.csv: ... no space left on device\"\n}\n\n// after: preflight disk space and fall back to an alternate output dir\nfunc ensureSpace(dir string, needBytes int64) error {\n\tvar st syscall.Statfs_t\n\tif err := syscall.Statfs(dir, &st); err != nil {\n\t\treturn err\n\t}\n\tif int64(st.Bavail)*int64(st.Bsize) < needBytes {\n\t\treturn fmt.Errorf(\"insufficient space in %s\", dir)\n\t}\n\treturn nil\n}\n\nif err := ensureSpace(outDir, 10<<20); err != nil {\n\toutDir = filepath.Join(os.TempDir(), \"hbd-export\") // fallback location\n}\nw, _ := output.NewWriter(outDir, \"csv\")","handlingStrategy":"try-catch","validationCode":"// Go has no try/catch; validate writable destination before calling Write()\nfunc dirIsWritable(dir string) error {\n\tif st, err := os.Stat(dir); err != nil || !st.IsDir() {\n\t\treturn fmt.Errorf(\"not a directory: %s\", dir)\n\t}\n\tprobe := filepath.Join(dir, \".hbd-write-probe\")\n\tf, err := os.OpenFile(probe, os.O_CREATE|os.O_WRONLY, 0o600)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif _, err := f.WriteString(\"x\"); err != nil { // catches full/read-only FS at write stage\n\t\tf.Close()\n\t\tos.Remove(probe)\n\t\treturn err\n\t}\n\tf.Close()\n\tos.Remove(probe)\n\treturn nil\n}\n\nif err := dirIsWritable(outDir); err != nil {\n\tlog.Fatalf(\"output dir not writable: %v\", err)\n}","typeGuard":"// Ensure the Writer was constructed with a valid, existing directory before Write()\nfunc validWriter(w *output.Writer, dir string) bool {\n\tst, err := os.Stat(dir)\n\treturn w != nil && err == nil && st.IsDir()\n}","tryCatchPattern":"// Go: inspect the wrapped error and classify the errno\nif err := w.Write(); err != nil {\n\tvar pe *os.PathError\n\tif errors.As(err, &pe) {\n\t\tswitch {\n\t\tcase errors.Is(pe.Err, syscall.ENOSPC):\n\t\t\tlog.Fatalf(\"disk full: free space on %s and retry\", outDir)\n\t\tcase errors.Is(pe.Err, syscall.EACCES), errors.Is(pe.Err, syscall.EROFS):\n\t\t\tlog.Fatalf(\"cannot write %s: check permissions/read-only mount\", pe.Path)\n\t\tdefault:\n\t\t\tlog.Fatalf(\"export failed: %v\", err)\n\t\t}\n\t}\n\tlog.Fatalf(\"export failed: %v\", err)\n}","preventionTips":["Pre-check free disk space on the target filesystem before running an export that may produce large history/download dumps.","Choose an output directory on a reliable local filesystem rather than network or removable mounts.","Run with a user account that owns or has write access to the output directory (avoid permission surprises from sudo-created dirs).","Monitor dmesg/system logs for filesystem errors if exports repeatedly fail on the same host.","Keep the wrapped error (%w) in logs — the inner errno (ENOSPC, EIO, EDQUOT) pinpoints the root cause faster than the filename alone."],"tags":["go","file-io","filesystem","disk-full"],"backgroundTag":"file-write-failed","analyzedSha":"0503d04d7a8d0379d060268a74f1b149e5a0aad5","analyzedAt":"2026-09-06T13:38:28.707Z","contentChangedAt":"2026-09-06T13:38:28.707Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}