{"record":{"id":"006f6e216ca3bc81","repo":"glanceapp/glance","slug":"creating-session-id-check-request-v","errorCode":null,"errorMessage":"creating session ID check request: %v","messagePattern":"creating session ID check request: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/glance/widget-dns-stats.go","lineNumber":669,"sourceCode":"\t\t\t\"authentication request returned status %s with message '%s'\",\n\t\t\tresponse.Status, jsonResponse.Session.Message,\n\t\t)\n\t}\n\n\tif jsonResponse.Session.SID == \"\" {\n\t\treturn \"\", fmt.Errorf(\n\t\t\t\"authentication response returned empty session ID, status code %d, message '%s'\",\n\t\t\tresponse.StatusCode, jsonResponse.Session.Message,\n\t\t)\n\t}\n\n\treturn jsonResponse.Session.SID, nil\n}\n\nfunc checkPiholeSessionIDIsValid(instanceURL string, client *http.Client, sessionID string) (bool, error) {\n\trequest, err := http.NewRequest(\"GET\", instanceURL+\"/api/auth\", nil)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"creating session ID check request: %v\", err)\n\t}\n\trequest.Header.Set(\"x-ftl-sid\", sessionID)\n\n\tresponse, err := client.Do(request)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\tdefer response.Body.Close()\n\n\tif response.StatusCode != http.StatusOK && response.StatusCode != http.StatusUnauthorized {\n\t\treturn false, fmt.Errorf(\"session ID check request returned status %s\", response.Status)\n\t}\n\n\treturn response.StatusCode == http.StatusOK, nil\n}\n\ntype technitiumStatsResponse struct {\n\tResponse struct {","sourceCodeStart":651,"sourceCodeEnd":687,"githubUrl":"https://github.com/glanceapp/glance/blob/91324e8de762702e97b0ac5c8e36271d644d8642/internal/glance/widget-dns-stats.go#L651-L687","documentation":"Thrown while building the GET <instanceURL>/api/auth request used to validate a Pi-hole session ID (header x-ftl-sid). http.NewRequest only fails when the URL cannot be parsed, so this indicates the configured Pi-hole instance URL is malformed (bad control characters, spaces, or an invalid scheme). The error wraps the underlying net/url parse error.","triggerScenarios":"checkPiholeSessionIDIsValid(instanceURL, ...) is called with an instanceURL that url.Parse rejects, e.g. 'http://192.168.1.10 :8080' (space), a URL with a pipe/control character, or an unparseable value from the widget's url: YAML field.","commonSituations":"Typo in the widget's url: setting (trailing spaces, missing scheme, copied URL with special characters); environment variable interpolation producing an empty or garbage URL.","solutions":["Check the widget's url: field for typos, spaces, or a missing http:// scheme","Print/inspect the effective instanceURL value right before the call and test it with curl","URL-encode any special characters in the URL (e.g. passwords in basic-auth path segments)"],"exampleFix":"# before\n- type: pi-hole\n  url: \"http://192.168.1.10 :8080\"\n# after\n- type: pi-hole\n  url: \"http://192.168.1.10:8080\"","handlingStrategy":"validation","validationCode":"u, err := url.Parse(instanceURL)\nif err != nil || u.Scheme == \"\" || u.Host == \"\" {\n    return fmt.Errorf(\"invalid pi-hole instance URL: %q\", instanceURL)\n}\nsid, err := fetchPiholeSession(instanceURL, client) // then validate","typeGuard":"func isValidInstanceURL(raw string) bool {\n    u, err := url.Parse(raw)\n    return err == nil && (u.Scheme == \"http\" || u.Scheme == \"https\") && u.Host != \"\"\n}","tryCatchPattern":"if valid, err := checkPiholeSessionIDIsValid(url, client, sid); err != nil {\n    slog.Warn(\"pi-hole session check failed\", \"url\", url, \"error\", err)\n    // fall back to unauthenticated stats rather than failing the widget\n} else if valid {\n    // use authenticated endpoint\n}","preventionTips":["Validate the pi-hole url: field with a URL parse + scheme check at config load time","Keep instance URLs in one place (env or anchors) so typos surface once, not per widget","Prefer FQDN/IP without paths; Pi-hole v6 API is at the base URL"],"tags":["pi-hole","url","configuration","validation"],"backgroundTag":null,"analyzedSha":"91324e8de762702e97b0ac5c8e36271d644d8642","analyzedAt":"2026-08-15T14:12:54.279Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}