shadow1ng/fscan · error
failed to write realtime backup: %w
Error message
failed to write realtime backup: %w
What it means
This error is returned by JSON-less (text) writers when writing a formatted line to the realtime backup file (.realtime.tmp) fails. The library keeps a realtime crash-safety backup of every scan result, so any disk write failure is surfaced immediately instead of being silently buffered. It wraps the underlying OS error via %w.
Source
Thrown at common/output/writers.go:137
func (w *TXTWriter) Write(result *ScanResult) error {
w.mu.Lock()
defer w.mu.Unlock()
if w.closed {
return fmt.Errorf("writer is closed")
}
if result == nil {
return fmt.Errorf("result cannot be nil")
}
// 1. 加入内存分类缓冲(用于最终有序输出)
w.buffer.Add(result)
// 2. 实时写入备份文件(防崩溃丢数据)
if w.realtimeFile != nil {
line := w.formatLine(result)
if _, err := w.realtimeFile.WriteString(line + "\n"); err != nil {
return fmt.Errorf("failed to write realtime backup: %w", err)
}
if err := w.realtimeFile.Sync(); err != nil {
return fmt.Errorf("failed to sync realtime backup: %w", err)
}
}
return nil
}
// getSeparator 获取分隔线文本
func (w *TXTWriter) getSeparator(newType ResultType) string {
switch newType {
case TypeHost:
return i18n.GetText("output_section_hosts")
case TypePort:
return i18n.GetText("output_section_ports")
case TypeService:
return i18n.GetText("output_section_services")View on GitHub (pinned to 95cc12e753)
Solutions
- Check disk space (df -h) and free space on the output volume
- Verify the output directory still exists and the process has write permission for the .realtime.tmp file
- Inspect the wrapped error (%w / errors.Unwrap) for the exact OS-level cause (ENOSPC, EBADF, EACCES)
- Reopen or recreate the writer pointing to a valid writable path
- If backup durability is not required, use a writer variant without realtime backup
Example fix
// before
if _, err := w.realtimeFile.WriteString(line + "\n"); err != nil {
return fmt.Errorf("failed to write realtime backup: %w", err)
}
// after
if _, err := w.realtimeFile.WriteString(line + "\n"); err != nil {
if errors.Is(err, syscall.ENOSPC) {
w.disableRealtimeBackup() // fall back to memory-only buffering
} else {
return fmt.Errorf("failed to write realtime backup: %w", err)
}
} Defensive patterns
Strategy: try-catch
Validate before calling
info, err := os.Stat(outDir)
if err != nil || !info.IsDir() { return fmt.Errorf("output dir missing") }
if unix.Access(outDir, unix.W_OK) != nil { return fmt.Errorf("output dir not writable") }
usable := syscall.Statfs_t{}
syscall.Statfs(outDir, &usable)
if usable.Bavail*uint64(usable.Bsize) < 64<<20 { return fmt.Errorf("low disk space") } Try / catch
if err := writer.Write(result); err != nil {
var pe *fs.PathError
if errors.As(err, &pe) && errors.Is(pe.Err, syscall.ENOSPC) {
// switch output volume or abort
}
return fmt.Errorf("backup write failed: %w", err)
} Prevention
- Monitor free disk space before and during scans
- Keep the output directory stable for the writer's lifetime
- Avoid writing to network filesystems for realtime backups
- Close writers exactly once, after all writes complete
- Check ulimit -n when opening many writers concurrently
When it happens
Trigger: Calling Write() on a writer whose realtimeFile is non-nil and whose underlying WriteString fails: disk full, file descriptor closed/invalid, permission revoked mid-run, or I/O error on the backing device.
Common situations: Disk quota exceeded during long scans; the .realtime.tmp file deleted or its directory removed while the process runs; running out of file descriptors after opening many writers; read-only filesystem remount.
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
- failed to sync realtime backup: %w
- failed to create JSON file: %w
- failed to create CSV file: %w
- failed to marshal result: %w
- parser_ipv4_only
AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06).
Data as JSON: /api/errors/d32fe3004b728bb1.
Report an issue: GitHub.