{"record":{"id":"e6e221cbc9fa7686","repo":"txthinking/brook","slug":"invalid-prefer","errorCode":null,"errorMessage":"Invalid prefer","messagePattern":"Invalid prefer","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/dialwithdns/dialwithdns.go","lineNumber":35,"sourceCode":"import (\n\t\"errors\"\n\t\"net\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/txthinking/brook\"\n\t\"github.com/txthinking/socks5\"\n)\n\ntype DialWithDNS struct {\n\tDNSClient *brook.DNSClient\n\tDOHClient *brook.DOHClient\n\tPrefer    string\n}\n\nfunc NewDialWithDNS(dns, prefer string) (*DialWithDNS, error) {\n\tif prefer != \"A\" && prefer != \"AAAA\" {\n\t\treturn nil, errors.New(\"Invalid prefer\")\n\t}\n\tif !strings.HasPrefix(dns, \"https://\") {\n\t\treturn &DialWithDNS{DNSClient: &brook.DNSClient{Server: dns}, Prefer: prefer}, nil\n\t}\n\tdc, err := brook.NewDOHClient(dns)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &DialWithDNS{DOHClient: dc, Prefer: prefer}, nil\n}\n\nfunc (p *DialWithDNS) IP(domain string) (net.IP, error) {\n\tif p.Prefer == \"A\" {\n\t\tif p.DNSClient != nil {\n\t\t\tip, err := p.DNSClient.A(domain)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/txthinking/brook/blob/5cd13ef3b1fb574e88ebf2c1b5d95f2ebe1342c8/plugins/dialwithdns/dialwithdns.go#L17-L53","documentation":"NewDialWithDNS validates the prefer parameter, which selects whether A (IPv4) or AAAA (IPv6) DNS records are queried. Any value other than the exact strings \"A\" or \"AAAA\" is rejected with \"Invalid prefer\" before a client is constructed.","triggerScenarios":"Calling NewDialWithDNS(dns, prefer) with prefer values like \"a\", \"ipv4\", \"A/AAAA\", \"\", or any other non-exact string; wiring the plugin with a mistyped config flag.","commonSituations":"Case-sensitivity mistakes (\"a\" instead of \"A\"); passing descriptive labels like \"ipv6\"; empty prefer read from an unset config value.","solutions":["Pass exactly \"A\" for IPv4 preference or \"AAAA\" for IPv6 preference.","Normalize/validate the config value before calling: uppercase it and map synonyms (\"ipv4\"->\"A\", \"ipv6\"->\"AAAA\").","Guard against empty values by defaulting to \"A\" when the config field is unset."],"exampleFix":"// before\np, err := NewDialWithDNS(dns, \"ipv4\")\n// after\nprefer := \"A\"\nif strings.EqualFold(cfg.Prefer, \"AAAA\") || strings.EqualFold(cfg.Prefer, \"ipv6\") {\n    prefer = \"AAAA\"\n}\np, err := NewDialWithDNS(dns, prefer)","handlingStrategy":"validation","validationCode":"func validPrefer(p string) bool { return p == \"A\" || p == \"AAAA\" }\nif !validPrefer(cfg.Prefer) { return fmt.Errorf(\"prefer must be \\\"A\\\" or \\\"AAAA\\\", got %q\", cfg.Prefer) }","typeGuard":null,"tryCatchPattern":"p, err := NewDialWithDNS(dns, prefer)\nif err != nil && strings.Contains(err.Error(), \"Invalid prefer\") {\n    prefer = \"A\" // safe default\n    p, err = NewDialWithDNS(dns, prefer)\n}","preventionTips":["Validate the prefer value at config-load time, before constructing plugins.","Normalize synonyms (ipv4/ipv6) to \"A\"/\"AAAA\" upstream.","Use constants instead of raw strings when calling NewDialWithDNS.","Remember the check is case-sensitive: \"a\" is invalid."],"tags":["dns","configuration","validation","ipv6"],"backgroundTag":"invalid-enum-value","analyzedSha":"5cd13ef3b1fb574e88ebf2c1b5d95f2ebe1342c8","analyzedAt":"2026-09-06T04:35:00.432Z","contentChangedAt":"2026-09-06T04:35:00.432Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}