{"record":{"id":"a0f1b15f4eaeb56e","repo":"netbirdio/netbird","slug":"invalid-filter-w","errorCode":null,"errorMessage":"invalid filter: %w","messagePattern":"invalid filter: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"client/cmd/capture.go","lineNumber":113,"sourceCode":"\t} else {\n\t\tcmd.PrintErrf(\"Capturing packets (pcap)... Press Ctrl+C to stop.\\n\")\n\t}\n\n\tstreamErr := streamCapture(ctx, cmd, stream, out)\n\tcleanupErr := cleanup()\n\tif streamErr != nil {\n\t\treturn streamErr\n\t}\n\treturn cleanupErr\n}\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\")","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/cmd/capture.go#L95-L131","documentation":"The capture command validates its positional filter with capture.ParseFilter before sending it to the daemon, and this error wraps the parser's rejection. The accepted grammar is a tcpdump-style subset: host IP, src/dst combined with host/port/net, bare port NUM, net PREFIX/LEN, protocol keywords (tcp, udp, icmp, icmp6, ip, ip6, proto NUM), and the boolean operators and/or/not with parentheses. Anything outside that grammar — unsupported tcpdump keywords, hostnames instead of literal IPs, malformed addresses — is rejected client-side before any RPC.","triggerScenarios":"Using tcpdump keywords the parser does not implement: portrange, less, greater, vlan, arp, ether host, 'port 443 and port 80' with duplicated qualifiers; passing a hostname (host myserver.example.com) where only a literal IP is accepted; an IP typo like 10.0.0 or 10.0.0.256; unbalanced parentheses '(host 10.0.0.1'; trailing tokens the parser did not consume (unexpected token ... at position N).","commonSituations":"Copy-pasting a working tcpdump expression into netbird debug capture; assuming full BPF support because the syntax looks like tcpdump; shell quoting issues that split the expression (usually fine since args are rejoined with spaces); using net 10.0.0.0/24 vs bare CIDR '10.0.0.0/24' which parses as a term only under net/host context.","solutions":["Re-read the grammar in the error's source file (util/capture/filter.go): rewrite the filter using only host/src/dst/port/net/tcp/udp/icmp/icmp6/ip/ip6/proto with and/or/not","Replace hostnames with literal IP addresses (resolve them yourself first: dig +short myhost)","Fix the specific parse error text — it names the offending token and position for unexpected-token cases","Test simpler sub-expressions incrementally: 'tcp' then 'host 10.0.0.1' then combine with and/or"],"exampleFix":"# before: unsupported keywords and a hostname\nnetbird debug capture portrange 80-90 or host api.example.com\n\n# after: literal IPs and supported keywords\nnetbird debug capture (port 80 or port 90) or host 203.0.113.10","handlingStrategy":"validation","validationCode":"// Validate before starting anything, exactly as the CLI does:\nif _, err := capture.ParseFilter(expr); err != nil {\n    return fmt.Errorf(\"invalid filter: %w\", err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Restrict filters to the documented grammar: host/src/dst/port/net + tcp/udp/icmp/icmp6/ip/ip6/proto with and/or/not","Resolve hostnames to IPs before building the expression — the parser accepts literal addresses only","Build complex filters incrementally, testing each sub-expression as you add it"],"tags":["capture","cli","bpf","filter","validation","tcpdump"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}