netbirdio/netbird · error
close output file: %w
Error message
close output file: %w
What it means
During output finalization the cleanup function closes the temp pcap file and accumulates a close error here. The data was already streamed; this indicates the close syscall itself failed, which is rare for local files and usually points to deferred write errors being reported at close time (NFS/network filesystems) or the descriptor being invalidated externally. It is collected into a multierror together with any later rename result.
Source
Thrown at client/cmd/capture.go:173
}
// captureOutput returns the writer for capture data and a cleanup function
// that finalizes the file. Errors from the cleanup must be propagated.
func captureOutput(cmd *cobra.Command) (io.Writer, func() error, error) {
outPath, _ := cmd.Flags().GetString("output")
if outPath == "" {
return os.Stdout, func() error { return nil }, nil
}
f, err := os.CreateTemp(filepath.Dir(outPath), filepath.Base(outPath)+".*.tmp")
if err != nil {
return nil, nil, fmt.Errorf("create output file: %w", err)
}
tmpPath := f.Name()
return f, func() error {
var merr *multierror.Error
if err := f.Close(); err != nil {
merr = multierror.Append(merr, fmt.Errorf("close output file: %w", err))
}
fi, statErr := os.Stat(tmpPath)
if statErr != nil || fi.Size() == 0 {
if rmErr := os.Remove(tmpPath); rmErr != nil && !os.IsNotExist(rmErr) {
merr = multierror.Append(merr, fmt.Errorf("remove empty output file: %w", rmErr))
}
return nberrors.FormatErrorOrNil(merr)
}
if err := os.Rename(tmpPath, outPath); err != nil {
merr = multierror.Append(merr, fmt.Errorf("rename output file: %w", err))
return nberrors.FormatErrorOrNil(merr)
}
cmd.PrintErrf("Wrote %s\n", outPath)
return nberrors.FormatErrorOrNil(merr)
}, nil
}
func handleCaptureError(err error) error {View on GitHub (pinned to 93e97f4bf1)
Solutions
- Retry the capture writing to a local filesystem (e.g. /tmp) and copy the file afterwards
- If on NFS, check mount health (dmesg, mount stats) and remount or move to local storage
- Check free space — a full disk can surface as an error at close rather than at write
- Update/report if it reproduces on a plain local ext4/xfs path, since that would be a genuine bug in the capture path
Example fix
# before: pcap written directly to a network mount netbird debug capture -d 30s -o /mnt/nfs/capture.pcap # after: capture locally, then copy cd /tmp && netbird debug capture -d 30s -o capture.pcap && cp capture.pcap /mnt/nfs/
Defensive patterns
Strategy: fallback
Validate before calling
// Prefer a local filesystem target for pcaps:
if isNetworkMount(dir) { // e.g. /proc/mounts type nfs|cifs|fuse
dir = os.TempDir()
} Try / catch
// Capture locally, copy after success:
if err := cleanup(); err != nil {
if isCloseOnly(err) { // data already flushed; copy from tmp if present
tryCopyTmpToFinal()
}
} Prevention
- Write pcaps to local disk and copy them afterwards
- Monitor mount health for long captures on network storage
- Watch disk space during long captures instead of discovering issues at close
When it happens
Trigger: --output on NFS or a network mount where flushed data fails at close; the process's file descriptor closed underneath it by an external tool or a filesystem forced unmount; SELinux/AppArmor interfering with the file after creation.
Common situations: Writing pcaps to a network share (home NFS, k8s hostPath with quirks); very long captures where the mount drops; exotic filesystems (FUSE) that return errors on close after background write failures.
Related errors
- remove empty output file: %w
- create output file: %w
- rename output file: %w
- invalid filter: %w
- duration must not be negative
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/158b9ffdc97db600.
Report an issue: GitHub.