{"record":{"id":"354e7ff0b3e73be5","repo":"netbirdio/netbird","slug":"parse-filter-w","errorCode":null,"errorMessage":"parse filter: %w","messagePattern":"parse filter: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/embed/embed.go","lineNumber":564,"sourceCode":"\treturn engine.SetPerformance(internal.Performance{\n\t\tPreallocatedBuffersPerPool: t.PreallocatedBuffersPerPool,\n\t})\n}\n\n// StartCapture begins capturing packets on this client's tunnel device.\n// Only one capture can be active at a time; starting a new one stops the previous.\n// Call StopCapture (or CaptureSession.Stop) to end it.\nfunc (c *Client) StartCapture(opts CaptureOptions) (*CaptureSession, error) {\n\tengine, err := c.getEngine()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar matcher capture.Matcher\n\tif opts.Filter != \"\" {\n\t\tm, err := capture.ParseFilter(opts.Filter)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"parse filter: %w\", err)\n\t\t}\n\t\tmatcher = m\n\t}\n\n\tsess, err := capture.NewSession(capture.Options{\n\t\tOutput:     opts.Output,\n\t\tTextOutput: opts.TextOutput,\n\t\tMatcher:    matcher,\n\t\tVerbose:    opts.Verbose,\n\t\tASCII:      opts.ASCII,\n\t})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"create capture session: %w\", err)\n\t}\n\n\tif err := engine.SetCapture(sess); err != nil {\n\t\tsess.Stop()\n\t\treturn nil, fmt.Errorf(\"set capture: %w\", err)","sourceCodeStart":546,"sourceCodeEnd":582,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/embed/embed.go#L546-L582","documentation":"Client.StartCapture parses opts.Filter with capture.ParseFilter, a small tcpdump-like grammar (host/net/port/src/dst/proto/tcp/udp/icmp/icmp6/ip/ip6 combined with and/or/not and parentheses). The error is returned when the expression violates that grammar, e.g. an incomplete term or a trailing unparsed token (\"unexpected token %q at position %d\"). An empty filter is valid and means match-all, so this error only fires on a non-empty malformed expression.","triggerScenarios":"StartCapture(CaptureOptions{Filter: \"tcp port\"}) (port with no number), \"port abc\", \"host not.an.ip\", unbalanced \"(host 10.0.0.1\", a leading \"and tcp\", or unsupported tcpdump primitives like \"ether host ..\", \"portrange 1000-2000\", \"tcp[tcpflags] & .. != 0\", \"less 100\".","commonSituations":"Copying a filter from a tcpdump/Wireshark cookbook into the embedded capture API; assuming full BPF/libpcap syntax is supported; user-supplied filter strings from a web UI reaching the API unvalidated.","solutions":["Rewrite the filter using only the supported grammar: host IP, src/dst target, port NUM, net PREFIX, protocol keywords, and/or/not, parentheses","Validate user-supplied filters by calling capture.ParseFilter (or a dry-run StartCapture/StopCapture) before the real capture","Strip unsupported primitives like ether/link-layer qualifiers, portrange, or byte-offset expressions"],"exampleFix":"// before\nsess, err := client.StartCapture(netbird.CaptureOptions{Filter: \"ether host aa:bb:cc:dd:ee:ff\", TextOutput: w})\n\n// after\nsess, err := client.StartCapture(netbird.CaptureOptions{Filter: \"host 10.0.0.5 and tcp port 443\", TextOutput: w})","handlingStrategy":"validation","validationCode":"// dry-run parse before starting the capture\nif opts.Filter != \"\" {\n    if _, err := capture.ParseFilter(opts.Filter); err != nil {\n        return fmt.Errorf(\"invalid capture filter: %w\", err)\n    }\n}","typeGuard":null,"tryCatchPattern":"sess, err := client.StartCapture(opts)\nif err != nil {\n    if strings.Contains(err.Error(), \"parse filter\") {\n        // user-input problem: surface it, do not retry\n        http.Error(w, err.Error(), http.StatusBadRequest)\n    }\n}","preventionTips":["Validate user-supplied filters server-side before passing them to StartCapture","Keep a whitelist of filter shapes your UI generates","Document the supported grammar (no ether/portrange/byte-offset primitives) next to the input field"],"tags":["go","capture","filter","parser","embed","validation"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}