{"record":{"id":"de4fd39d844ca22c","repo":"txthinking/brook","slug":"err-error","errorCode":null,"errorMessage":"err.Error()","messagePattern":"err\\.Error\\(\\)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"warning","filePath":"dohserver.go","lineNumber":164,"sourceCode":"\t\t\tRetry:   3600,\n\t\t\tExpire:  259200,\n\t\t\tMinttl:  300,\n\t\t})\n\t\tm1b, err := m1.PackBuffer(nil)\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\tw.Header().Set(\"Content-Type\", \"application/dns-message\")\n\t\tw.Write(m1b)\n\t\treturn true, nil\n\t}\n\treturn false, nil\n}\n\nfunc (s *DOHServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {\n\tb, err := io.ReadAll(r.Body)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), 500)\n\t\treturn\n\t}\n\tm := &dns.Msg{}\n\tif err := m.Unpack(b); err != nil {\n\t\thttp.Error(w, err.Error(), 500)\n\t\treturn\n\t}\n\tdone, err := DOHGate(m, w, r)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), 500)\n\t\treturn\n\t}\n\tif done {\n\t\treturn\n\t}\n\tm1 := &dns.Msg{}\n\tif s.DNSClient != nil {\n\t\tm1, err = s.DNSClient.Exchange(m)","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/txthinking/brook/blob/5cd13ef3b1fb574e88ebf2c1b5d95f2ebe1342c8/dohserver.go#L146-L182","documentation":"DOHServer.ServeHTTP reads the entire request body before treating it as a DNS message. If io.ReadAll fails (client aborted mid-upload, body stream error, timeout), the server responds with HTTP 500 carrying the underlying error text. The error message is dynamic - it is whatever io.ReadAll returned.","triggerScenarios":"A DoH POST whose body stream breaks: client disconnects before the full body arrives, connection reset, body larger than the server's read limits, or network interruption during upload.","commonSituations":"Mobile clients dropping connections mid-request; aggressive client timeouts smaller than upload time; load balancer cutting the connection; malformed chunked transfer encoding.","solutions":["Retry the DNS query from the client with an intact connection","Check client-side timeouts and keep-alive settings so the body completes","Verify no intermediary (proxy/LB) terminates long uploads; raise its body/timeout limits","Inspect the specific error text in the 500 response to target the root cause (reset vs timeout)","Consider sending the query via GET (RFC 8484 ?dns= parameter) to avoid upload truncation"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"resp, err := http.Post(dohURL, \"application/dns-message\", body)\nif err != nil || resp.StatusCode == 500 {\n\t// transient body/read failure: rebuild query and retry with backoff\n\ttime.Sleep(backoff); retry()\n}","preventionTips":["Use client timeouts longer than worst-case upload time","Prefer GET with ?dns= for small queries","Avoid uploading large bodies over flaky links"],"tags":["doh","dns","http"],"backgroundTag":"http-error-response","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"}