{"record":{"id":"3f89730322fb4226","repo":"netbirdio/netbird","slug":"rename-output-file-w","errorCode":null,"errorMessage":"rename output file: %w","messagePattern":"rename output file: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/cmd/capture.go","lineNumber":183,"sourceCode":"\tf, err := os.CreateTemp(filepath.Dir(outPath), filepath.Base(outPath)+\".*.tmp\")\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"create output file: %w\", err)\n\t}\n\ttmpPath := f.Name()\n\treturn f, func() error {\n\t\tvar merr *multierror.Error\n\t\tif err := f.Close(); err != nil {\n\t\t\tmerr = multierror.Append(merr, fmt.Errorf(\"close output file: %w\", err))\n\t\t}\n\t\tfi, statErr := os.Stat(tmpPath)\n\t\tif statErr != nil || fi.Size() == 0 {\n\t\t\tif rmErr := os.Remove(tmpPath); rmErr != nil && !os.IsNotExist(rmErr) {\n\t\t\t\tmerr = multierror.Append(merr, fmt.Errorf(\"remove empty output file: %w\", rmErr))\n\t\t\t}\n\t\t\treturn nberrors.FormatErrorOrNil(merr)\n\t\t}\n\t\tif err := os.Rename(tmpPath, outPath); err != nil {\n\t\t\tmerr = multierror.Append(merr, fmt.Errorf(\"rename output file: %w\", err))\n\t\t\treturn nberrors.FormatErrorOrNil(merr)\n\t\t}\n\t\tcmd.PrintErrf(\"Wrote %s\\n\", outPath)\n\t\treturn nberrors.FormatErrorOrNil(merr)\n\t}, nil\n}\n\nfunc handleCaptureError(err error) error {\n\tif s, ok := status.FromError(err); ok {\n\t\treturn fmt.Errorf(\"%s\", s.Message())\n\t}\n\treturn err\n}\n","sourceCodeStart":165,"sourceCodeEnd":197,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/cmd/capture.go#L165-L197","documentation":"The final atomic-publish step of pcap output: os.Rename of the temp file onto the requested --output path failed. The temp file lives in the same directory by design, so cross-device rename (EXDEV) should not occur — the realistic causes are a missing target directory, a target that is an existing directory, or permission issues on the directory/name. The capture data itself is lost from the final path when this fires (the temp file may remain).","triggerScenarios":"The output directory was removed between capture start and finish (tmp cleaner, scripted cleanup of /tmp); --output names an existing directory (netbird debug capture -o /tmp — basename '/tmp.*.tmp' created in / renames onto /tmp); directory not writable for rename (w+x needed) though CreateTemp succeeded via a race; target file exists and is owned by another user on systems where rename over it is denied.","commonSituations":"Long captures into systemd-tmpfiles-cleaned /tmp: cleaner wipes the dir mid-run; output path supplied by a script that also mkdirs/rms concurrently; -o pointing at a mountpoint root.","solutions":["Confirm the parent directory of -o still exists when the capture ends; for long captures prefer a stable directory (e.g. /var/tmp or $HOME) that tmp cleaners do not purge","Never pass a directory as -o; the value must be a file path","If a stray .tmp file remains next to the target, rename it manually: mv /path/x.pcap.*.tmp /path/x.pcap to salvage the data","Re-run with a shorter --duration to verify the path works, then scale up"],"exampleFix":"# before: long capture into a cleaned tmp dir\nnetbird debug capture -d 24h -o /tmp/long.pcap\n\n# after: durable location\nnetbird debug capture -d 24h -o /var/tmp/netbird/long.pcap   # mkdir -p /var/tmp/netbird first","handlingStrategy":"validation","validationCode":"// Ensure the parent exists and is a real directory, and the target name is not a dir:\ndir := filepath.Dir(outPath)\nif err := os.MkdirAll(dir, 0o755); err != nil { return err }\nif fi, err := os.Stat(outPath); err == nil && fi.IsDir() {\n    return fmt.Errorf(\"%s is a directory\", outPath)\n}","typeGuard":null,"tryCatchPattern":"// After a rename failure, salvage data from the temp file:\nif err := os.Rename(tmpPath, outPath); err != nil {\n    if data, rerr := os.ReadFile(tmpPath); rerr == nil {\n        os.WriteFile(outPath+\".recovered\", data, 0o644)\n    }\n    return err\n}","preventionTips":["Never point -o at a mountpoint root or an existing directory","For long captures use a directory no tmp-cleaner purges (/var/tmp over /tmp)","Pass an absolute path so a changed cwd cannot redirect the rename target"],"tags":["capture","filesystem","rename","atomic-write","cli"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}