{"record":{"id":"7802ddc8a08b4764","repo":"glanceapp/glance","slug":"reading-authentication-response-v","errorCode":null,"errorMessage":"reading authentication response: %v","messagePattern":"reading authentication response: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/glance/widget-dns-stats.go","lineNumber":635,"sourceCode":"\nfunc fetchPiholeSessionID(instanceURL string, client *http.Client, password string) (string, error) {\n\trequestBody := []byte(`{\"password\":\"` + password + `\"}`)\n\n\trequest, err := http.NewRequest(\"POST\", instanceURL+\"/api/auth\", bytes.NewBuffer(requestBody))\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"creating authentication request: %v\", err)\n\t}\n\trequest.Header.Set(\"Content-Type\", \"application/json\")\n\n\tresponse, err := client.Do(request)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"sending authentication request: %v\", err)\n\t}\n\tdefer response.Body.Close()\n\n\tbody, err := io.ReadAll(response.Body)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"reading authentication response: %v\", err)\n\t}\n\n\tvar jsonResponse struct {\n\t\tSession struct {\n\t\t\tSID     string `json:\"sid\"`\n\t\t\tMessage string `json:\"message\"`\n\t\t} `json:\"session\"`\n\t}\n\n\tif err := json.Unmarshal(body, &jsonResponse); err != nil {\n\t\treturn \"\", fmt.Errorf(\"parsing authentication response: %v\", err)\n\t}\n\n\tif response.StatusCode != http.StatusOK {\n\t\treturn \"\", fmt.Errorf(\n\t\t\t\"authentication request returned status %s with message '%s'\",\n\t\t\tresponse.Status, jsonResponse.Session.Message,\n\t\t)","sourceCodeStart":617,"sourceCodeEnd":653,"githubUrl":"https://github.com/glanceapp/glance/blob/91324e8de762702e97b0ac5c8e36271d644d8642/internal/glance/widget-dns-stats.go#L617-L653","documentation":"Returned by fetchPiholeSessionID when io.ReadAll(response.Body) fails while reading the auth response body. Rare: the request succeeded and headers were received, but the stream aborted mid-body — connection reset during transfer, premature close, or a read timeout.","triggerScenarios":"Upstream or an intermediary proxy closes the connection before Content-Length bytes arrive; client read timeout shorter than the server's response time; connection reset by a firewall or load balancer.","commonSituations":"Flaky Wi-Fi/VPN link to a self-hosted Pi-hole; aggressive proxy idle timeouts; Pi-hole restarting exactly while responding.","solutions":["Retry — transient mid-body failures usually clear on the next widget refresh.","If persistent, capture whether a proxy between glance and Pi-hole truncates responses.","Increase client timeouts if the Pi-hole host is slow (high load).","Verify with a large curl of the same endpoint that the body transfers fully."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"reading authentication response\") {\n    // mid-body abort: almost always transient — rely on the next refresh\n    slog.Warn(\"pihole auth body read failed, will retry\", \"error\", err)\n}","preventionTips":["Treat mid-body read failures as transient; do not reconfigure on a single occurrence.","Stabilize flaky links/VPNs between glance and the Pi-hole host.","Ensure proxies do not truncate responses (check Content-Length vs delivered bytes)."],"tags":["network","pihole","io","dns-stats"],"backgroundTag":null,"analyzedSha":"91324e8de762702e97b0ac5c8e36271d644d8642","analyzedAt":"2026-08-15T14:12:54.279Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}