{"record":{"id":"c1953165254cd3a5","repo":"AdguardTeam/AdGuardHome","slug":"invalid-ip-version-d","errorCode":null,"errorMessage":"invalid ip version %d","messagePattern":"invalid ip version (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/aghnet/interfaces.go","lineNumber":32,"sourceCode":"\n// IP version constants.\nconst (\n\tIPVersion4 IPVersion = 4\n\tIPVersion6 IPVersion = 6\n)\n\n// NetIface is the interface for network interface methods.\ntype NetIface interface {\n\tAddrs() ([]net.Addr, error)\n}\n\n// IfaceIPAddrs returns the interface's IP addresses.  iface must not be nil.\nfunc IfaceIPAddrs(iface NetIface, ipv IPVersion) (ips []net.IP, err error) {\n\tswitch ipv {\n\tcase IPVersion4, IPVersion6:\n\t\t// Go on.\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"invalid ip version %d\", ipv)\n\t}\n\n\taddrs, err := iface.Addrs()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tfor _, a := range addrs {\n\t\tif ip := ipFromAddr(a, ipv); ip != nil {\n\t\t\tips = append(ips, ip)\n\t\t}\n\t}\n\n\treturn ips, nil\n}\n\n// ipFromAddr converts addr to IP.  addr must not be nil.\nfunc ipFromAddr(addr net.Addr, ipv IPVersion) (ip net.IP) {","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/AdguardTeam/AdGuardHome/blob/b41aefbe51c8dde65e2c50f093996afa0502edf9/internal/aghnet/interfaces.go#L14-L50","documentation":"The query-log search parser encountered a criterion type that is not one of ctTerm, ctFilteringStatus, or ctReason. The parser dispatches on the criterion prefix inside the search expression; an unrecognized prefix/type falls through to this default case listing the valid types.","triggerScenarios":"GET /control/querylog?search=... where the search expression contains a criterion whose type (text before the parentheses) is not term/filtering_status/reason, e.g. search=client(x) or a stray 'name(' in the expression.","commonSituations":"Copy-pasting search syntax from a different product or older version; unescaped parentheses in a free-text term being parsed as a criterion; client sending a new criterion type to an older server.","solutions":["Rewrite the search using only term, filtering_status, and reason criteria","Escape or remove parentheses in plain-text search terms","Upgrade the server if the client legitimately needs a newer criterion type","Inspect parseSearchCriterion's dispatch to see exact recognized prefixes"],"exampleFix":"// before\nGET /control/querylog?search=device(laptop)\n// after\nGET /control/querylog?search=laptop","handlingStrategy":"validation","validationCode":"var validTypes = map[string]bool{\"term\": true, \"filtering_status\": true, \"reason\": true}\nif !validTypes[critType] { skip() }","typeGuard":"func isValidCriterion(c string) bool {\n    t := c[:strings.IndexByte(c, '(')]\n    return t == \"\" || validTypes[t]\n}","tryCatchPattern":"if resp.StatusCode == 400 && strings.Contains(body, \"invalid criterion type\") {\n    // rewrite query using plain terms only\n}","preventionTips":["Escape parentheses in free-text terms","Keep search syntax in a shared client module","Version-gate new criterion types against server capabilities"],"tags":["querylog","search","http","validation","go"],"backgroundTag":"enum-validation-failed","analyzedSha":"b41aefbe51c8dde65e2c50f093996afa0502edf9","analyzedAt":"2026-08-27T04:57:55.097Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}