netbirdio/netbird · warning
remove empty output file: %w
Error message
remove empty output file: %w
What it means
In output finalization, when the temp file is empty (zero packets captured) or its Stat failed, the cleanup removes the temp file so no stray .tmp file is left behind. This error means os.Remove failed with something other than 'file does not exist' — e.g. permission loss on the directory between creation and removal, or the file being held immutable. It is accumulated into the returned multierror.
Source
Thrown at client/cmd/capture.go:178
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 {
if s, ok := status.FromError(err); ok {
return fmt.Errorf("%s", s.Message())
}
return err
}View on GitHub (pinned to 93e97f4bf1)
Solutions
- Check directory permissions and MAC denials (ausearch -m AVC for SELinux) for the output directory
- Ensure no antivirus/EDR is removing or locking the .tmp files; exclude the capture directory if policy allows
- Retry with an output directory you fully control (e.g. under /tmp)
- If Stat failed rather than Remove, the temp file may already be gone — verify no stray *.tmp remains and treat the message as diagnostic
Example fix
# before: writing where a policy tool intervenes netbird debug capture -o /opt/protected/x.pcap # after: use a controlled writable directory netbird capture -o /tmp/x.pcap 2>/dev/null || netbird debug capture -o "$HOME/x.pcap"
Defensive patterns
Strategy: fallback
Validate before calling
// Reduce exposure: use a dedicated, policy-free output dir owned by the invoker: // mkdir -p ~/netbird-captures && netbird debug capture -o ~/netbird-captures/x.pcap
Try / catch
// Best-effort cleanup: ignore remove failures for empty temp files, they are cosmetic:
if rmErr := os.Remove(tmpPath); rmErr != nil && !os.IsNotExist(rmErr) {
log.Warnf("leftover temp file %s: %v", tmpPath, rmErr)
} Prevention
- Keep the output directory owned by the invoking user to avoid permission drift mid-run
- Exclude capture directories from antivirus/EDR quarantine policies
- If a stray .tmp remains, delete it manually; it contains no useful data when empty
When it happens
Trigger: Directory permissions changed or the process lost write permission on the output directory between CreateTemp and cleanup; another process/user deleted or locked the temp file on platforms that disallow removal; immutable attribute (chattr +i) set on the file.
Common situations: Security tooling quarantining pcap-like temp files mid-run; permission-revoking MAC policy (SELinux) reacting to the new file; extremely rare in normal single-user CLI use — usually seen together with unusual cleanup failures of the same run.
Related errors
- create output file: %w
- close output file: %w
- rename output file: %w
- write private key file (%s): %w
- write public key file (%s): %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/403bb0d2bc3ea824.
Report an issue: GitHub.