{"record":{"id":"91e37555349650bf","repo":"go-delve/delve","slug":"channel-filter-can-not-be-negated","errorCode":null,"errorMessage":"channel filter can not be negated","messagePattern":"channel filter can not be negated","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"service/rpc2/server.go","lineNumber":705,"sourceCode":"// be grouped with the specified criterion.\n// If the value of arg.GroupBy is GoroutineLabel goroutines will\n// be grouped by the value of the label with key GroupByKey.\n// For each group a maximum of MaxGroupMembers example goroutines are\n// returned, as well as the total number of goroutines in the group.\nfunc (s *RPCServer) ListGoroutines(arg ListGoroutinesIn, out *ListGoroutinesOut) error {\n\t//TODO(aarzilli): if arg contains a running goroutines filter (not negated)\n\t// and start == 0 and count == 0 then we can optimize this by just looking\n\t// at threads directly.\n\n\tvar gs []*proc.G\n\tvar nextg int\n\tvar err error\n\tvar gsLoaded bool\n\n\tfor _, filter := range arg.Filters {\n\t\tif filter.Kind == api.GoroutineWaitingOnChannel {\n\t\t\tif filter.Negated {\n\t\t\t\treturn errors.New(\"channel filter can not be negated\")\n\t\t\t}\n\t\t\tif arg.Count == 0 {\n\t\t\t\treturn errors.New(\"count == 0 not allowed with a channel filter\")\n\t\t\t}\n\t\t\tif arg.EvalScope == nil {\n\t\t\t\treturn errors.New(\"channel filter without eval scope\")\n\t\t\t}\n\t\t\tgs, err = s.debugger.ChanGoroutines(arg.EvalScope.GoroutineID, arg.EvalScope.Frame, arg.EvalScope.DeferredCall, filter.Arg, arg.Start, arg.Count)\n\t\t\tif len(gs) == arg.Count {\n\t\t\t\tnextg = arg.Start + len(gs)\n\t\t\t} else {\n\t\t\t\tnextg = -1\n\t\t\t}\n\t\t\tgsLoaded = true\n\t\t\tbreak\n\t\t}\n\t}\n","sourceCodeStart":687,"sourceCodeEnd":723,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/service/rpc2/server.go#L687-L723","documentation":"ListGoroutines with a GoroutineWaitingOnChannel filter rejects negated channel filters. Channel-wait filtering is implemented by evaluating a receive/send expression in the target's scope, so negation ('goroutines NOT waiting on channel X') cannot be computed and is explicitly refused.","triggerScenarios":"Sending a ListGoroutines RPC where arg.Filters contains {Kind: GoroutineWaitingOnChannel, Negated: true}.","commonSituations":"IDE or custom client building a goroutine filter UI that toggles a 'not' checkbox on a channel filter.","solutions":["Set Negated=false on the channel filter.","Express the inverse by fetching channel waiters and filtering on the client side.","Use a different filter kind that supports negation."],"exampleFix":"// before\nfilters := []api.ListGoroutinesFilter{{Kind: api.GoroutineWaitingOnChannel, Arg: chAddr, Negated: true}}\n// after\nfilters := []api.ListGoroutinesFilter{{Kind: api.GoroutineWaitingOnChannel, Arg: chAddr, Negated: false}}","handlingStrategy":"validation","validationCode":"for _, f := range filters {\n    if f.Kind == api.GoroutineWaitingOnChannel && f.Negated {\n        return errors.New(\"channel filters must not be negated\")\n    }\n}","typeGuard":null,"tryCatchPattern":"err := client.Call(\"RPCServer.ListGoroutines\", in, &out)\nif err != nil && strings.Contains(err.Error(), \"can not be negated\") {\n    // rebuild filter with Negated=false and retry\n}","preventionTips":["Never set Negated on GoroutineWaitingOnChannel filters.","Filter UI: hide the negate toggle for channel filters.","Filter out unsupported kinds client-side before the RPC."],"tags":["go","rpc","goroutines","filter","validation"],"backgroundTag":"unsupported-filter-negation","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}