{"record":{"id":"b21247518e8379b8","repo":"glanceapp/glance","slug":"fetching-session-id-v","errorCode":null,"errorMessage":"fetching session ID: %v","messagePattern":"fetching session ID: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/glance/widget-dns-stats.go","lineNumber":435,"sourceCode":"\tincludeGraph bool,\n\tincludeTopDomains bool,\n) (*dnsStats, string, error) {\n\tinstanceURL = strings.TrimRight(instanceURL, \"/\")\n\tvar client = ternary(allowInsecure, defaultInsecureHTTPClient, defaultHTTPClient)\n\n\tfetchNewSessionID := func() error {\n\t\tnewSessionID, err := fetchPiholeSessionID(instanceURL, client, password)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tsessionID = newSessionID\n\t\treturn nil\n\t}\n\n\tif sessionID == \"\" {\n\t\tif err := fetchNewSessionID(); err != nil {\n\t\t\tslog.Error(\"Failed to fetch Pihole v6 session ID\", \"error\", err)\n\t\t\treturn nil, \"\", fmt.Errorf(\"fetching session ID: %v\", err)\n\t\t}\n\t} else {\n\t\tisValid, err := checkPiholeSessionIDIsValid(instanceURL, client, sessionID)\n\t\tif err != nil {\n\t\t\tslog.Error(\"Failed to check Pihole v6 session ID validity\", \"error\", err)\n\t\t\treturn nil, \"\", fmt.Errorf(\"checking session ID: %v\", err)\n\t\t}\n\n\t\tif !isValid {\n\t\t\tif err := fetchNewSessionID(); err != nil {\n\t\t\t\tslog.Error(\"Failed to renew Pihole v6 session ID\", \"error\", err)\n\t\t\t\treturn nil, \"\", fmt.Errorf(\"renewing session ID: %v\", err)\n\t\t\t}\n\t\t}\n\t}\n\n\tvar wg sync.WaitGroup\n\tctx, cancel := context.WithCancel(context.Background())","sourceCodeStart":417,"sourceCodeEnd":453,"githubUrl":"https://github.com/glanceapp/glance/blob/91324e8de762702e97b0ac5c8e36271d644d8642/internal/glance/widget-dns-stats.go#L417-L453","documentation":"Returned by the Pi-hole v6 stats fetcher when no cached session ID exists and fetchPiholeSessionID fails to obtain one via POST /api/auth. The wrapped error is one of: creating/sending the auth request, reading/parsing its response, a non-200 status, or an empty SID. The failure is also logged via slog before being returned.","triggerScenarios":"widget.Service=pihole_v6 with a wrong password (auth returns 401), unreachable instance URL, TLS errors when allow-insecure is not set, or an auth response that is not the expected JSON.","commonSituations":"Pi-hole upgraded to v6 where the old ?auth= query param no longer works; password containing characters needing YAML quoting; glance running in a different network that cannot reach the Pi-hole host.","solutions":["Verify the password exactly matches the Pi-hole v6 web UI password (quote it in YAML if it has special characters).","curl -X POST {url}/api/auth -d '{\"password\":\"...\"}' and confirm a 200 with a session.sid.","Check network reachability/TLS from the glance host; set allow-insecure: true only for self-signed labs.","Confirm the instance really runs Pi-hole v6 — v5 instances need service: pihole instead."],"exampleFix":"# before\n- type: dns-stats\n  service: pihole_v6\n  url: http://pihole.local/admin\n  password: my$ecret\n\n# after\n- type: dns-stats\n  service: pihole_v6\n  url: http://pihole.local\n  password: \"my$ecret\"","handlingStrategy":"retry","validationCode":"// pre-flight: can we authenticate at all?\nif sid, err := fetchPiholeSessionID(url, client, password); err != nil {\n    return fmt.Errorf(\"pihole_v6 auth preflight failed: %v\", err)\n} else if sid == \"\" {\n    return errors.New(\"pihole_v6 returned empty session\")\n}","typeGuard":null,"tryCatchPattern":"stats, sid, err := fetchPiholeV6Stats(...)\nif err != nil && strings.HasPrefix(err.Error(), \"fetching session ID\") {\n    // auth path failure: check password/reachability, skip this refresh\n    slog.Warn(\"pihole auth failed\", \"error\", err)\n    return\n}","preventionTips":["Quote the password in YAML to protect special characters.","Confirm Pi-hole v6 (not v5) — v5 needs service: pihole.","Point url at the instance root; the code appends /api paths."],"tags":["network","auth","pihole","dns-stats","widget"],"backgroundTag":null,"analyzedSha":"91324e8de762702e97b0ac5c8e36271d644d8642","analyzedAt":"2026-08-15T14:12:54.279Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}