netbirdio/netbird · error
create output file: %w
Error message
create output file: %w
What it means
captureOutput creates the pcap output as a temp file in the same directory as the requested --output path (basename + .*.tmp) via os.CreateTemp, and this wraps that failure. Creating in the target directory is deliberate — the finalize step renames the temp file onto the final path atomically, so a temp file on another filesystem would break the rename. The error means the directory itself could not host a new file.
Source
Thrown at client/cmd/capture.go:167
return handleCaptureError(err)
}
if _, err := out.Write(pkt.GetData()); err != nil {
return fmt.Errorf("write output: %w", err)
}
}
}
// 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)
}View on GitHub (pinned to 93e97f4bf1)
Solutions
- Create the parent directory first: mkdir -p /var/captures, then rerun with -o /var/captures/x.pcap
- Check write permission on the directory (ls -ld, id) and choose a writable path or run with appropriate privileges
- Verify the filesystem is not read-only or full: mount | grep <dir>, df -h <dir>
- Prefer an absolute path for -o to avoid cwd surprises
Example fix
# before: parent directory does not exist netbird debug capture -o /var/captures/x.pcap # after: create it first mkdir -p /var/captures && netbird debug capture -o /var/captures/x.pcap
Defensive patterns
Strategy: validation
Validate before calling
// Verify writability of the output directory before starting the capture:
dir := filepath.Dir(outPath)
if info, err := os.Stat(dir); err != nil || !info.IsDir() {
return fmt.Errorf("output directory %s missing", dir)
}
probe, err := os.CreateTemp(dir, ".probe")
if err != nil {
return fmt.Errorf("cannot write in %s: %v", dir, err)
}
os.Remove(probe.Name()) Prevention
- mkdir -p the output directory as part of any wrapper script
- Always pass an absolute file path to -o; never a directory
- Prefer /var/tmp or a data dir over /tmp for long-lived captures
When it happens
Trigger: --output points into a directory that does not exist (netbird debug capture -o /var/captures/x.pcap with /var/captures missing); no write permission on the directory (running unprivileged, writing to /root or a root-owned dir); read-only or full filesystem (EROFS, ENOSPC); -o with a bare filename while cwd is not writable.
Common situations: Typo in the output path; expecting the tool to mkdir -p parent directories (it does not); running as non-root where the CLI default dirs are root-owned; container/CI with a read-only volume as the output location.
Related errors
- remove empty 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/1f0b79827409c7df.
Report an issue: GitHub.