{"record":{"id":"98d05617ceb85d83","repo":"netbirdio/netbird","slug":"duration-must-not-be-negative","errorCode":null,"errorMessage":"duration must not be negative","messagePattern":"duration must not be negative","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"client/cmd/capture.go","lineNumber":123,"sourceCode":"}\n\nfunc buildCaptureRequest(cmd *cobra.Command, args []string) (*proto.StartCaptureRequest, error) {\n\treq := &proto.StartCaptureRequest{}\n\n\tif len(args) > 0 {\n\t\texpr := strings.Join(args, \" \")\n\t\tif _, err := capture.ParseFilter(expr); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid filter: %w\", err)\n\t\t}\n\t\treq.FilterExpr = expr\n\t}\n\n\tif snap, _ := cmd.Flags().GetUint32(\"snap-len\"); snap > 0 {\n\t\treq.SnapLen = snap\n\t}\n\tif d, _ := cmd.Flags().GetDuration(\"duration\"); d != 0 {\n\t\tif d < 0 {\n\t\t\treturn nil, fmt.Errorf(\"duration must not be negative\")\n\t\t}\n\t\treq.Duration = durationpb.New(d)\n\t}\n\treq.Verbose, _ = cmd.Flags().GetBool(\"verbose\")\n\treq.Ascii, _ = cmd.Flags().GetBool(\"ascii\")\n\n\toutPath, _ := cmd.Flags().GetString(\"output\")\n\tforcePcap, _ := cmd.Flags().GetBool(\"pcap\")\n\treq.TextOutput = !forcePcap && outPath == \"\"\n\n\treturn req, nil\n}\n\nfunc streamCapture(ctx context.Context, cmd *cobra.Command, stream proto.DaemonService_StartCaptureClient, out io.Writer) error {\n\tfor {\n\t\tpkt, err := stream.Recv()\n\t\tif err != nil {\n\t\t\tif ctx.Err() != nil {","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/cmd/capture.go#L105-L141","documentation":"buildCaptureRequest reads the --duration/-d flag and refuses a negative value: a non-zero negative duration would be meaningless for the capture (the daemon stops the stream after the elapsed duration). It is a pure client-side flag validation, raised before the gRPC stream is opened.","triggerScenarios":"Passing an explicitly negative duration: netbird debug capture --duration=-30s or -d -1m; a shell alias or script computing the duration from a subtraction that went negative (END-START where END < START, producing e.g. -45s). Note d != 0 gates the check, so zero means 'until interrupted' and is allowed.","commonSituations":"Automation scripts that compute a countdown and pass it through without clamping; typo of the minus sign; reusing a timeout budget variable that has already been spent.","solutions":["Pass a positive duration (netbird debug capture -d 30s) or omit the flag to run until Ctrl+C","If the value is computed, clamp it: use the value only when > 0, e.g. netbird debug capture -d \"${remaining}s\" after checking remaining>0","Double-check for a stray leading dash introduced by flag style: --duration=-5s is parsed as the value -5s, which this check catches"],"exampleFix":"# before: computed value may be negative\nnetbird debug capture -d $((END-NOW))s\n\n# after: guard in the caller or clamp\nremaining=$((END-NOW)); [ \"$remaining\" -lt 1 ] && remaining=1\nnetbird debug capture -d ${remaining}s","handlingStrategy":"validation","validationCode":"// In scripts, clamp before invoking:\nd=${CALC_SECONDS:-0}\nif [ \"$d\" -gt 0 ] 2>/dev/null; then DUR=\"${d}s\"; else DUR=\"\"; fi\nnetbird debug capture -d \"$DUR\" # empty resets to default 0","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat duration as an unsigned value in any wrapper; clamp negatives to zero (which means run-forever) or a floor of 1s","Compute durations from max(1, END-NOW) so a slow start cannot produce a negative budget"],"tags":["cli","capture","validation","flags","duration"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}