glanceapp/glance · error
fetching stats: %v
Error message
fetching stats: %v
What it means
Returned by the Pi-hole v6 stats fetcher after all parallel requests complete: the primary stats request (statsErr) failed, which is fatal — unlike the graph (series) and top-domains requests, whose failures only downgrade to errPartialContent. The wrapped error comes from decodeJsonFromRequest on the main stats endpoint.
Source
Thrown at internal/glance/widget-dns-stats.go:532
var topDomainsResponse topDomainsResponseJson
var topDomainsErr error
if includeTopDomains {
topDomainsRequest, _ := http.NewRequestWithContext(ctx, "GET", instanceURL+"/api/stats/top_domains?blocked=true", nil)
topDomainsRequest.Header.Set("x-ftl-sid", sessionID)
wg.Add(1)
go func() {
defer wg.Done()
topDomainsResponse, topDomainsErr = decodeJsonFromRequest[topDomainsResponseJson](client, topDomainsRequest)
}()
}
wg.Wait()
partialContent := false
if statsErr != nil {
return nil, "", fmt.Errorf("fetching stats: %v", statsErr)
}
if includeGraph && seriesErr != nil {
slog.Error("Failed to fetch Pihole v6 graph data", "error", seriesErr)
partialContent = true
}
if includeTopDomains && topDomainsErr != nil {
slog.Error("Failed to fetch Pihole v6 top domains", "error", topDomainsErr)
partialContent = true
}
stats := &dnsStats{
TotalQueries: statsResponse.Queries.Total,
BlockedQueries: statsResponse.Queries.Blocked,
BlockedPercent: int(statsResponse.Queries.PercentBlocked),
DomainsBlocked: statsResponse.Gravity.DomainsBlocked,
}View on GitHub (pinned to 91324e8de7)
Solutions
- Check the wrapped error for status vs transport: 401 means session/auth trouble, timeouts mean load/network.
- curl -H 'X-Session: <sid>' {url}/api/stats after authenticating to verify the endpoint responds 200 JSON.
- Ensure the widget url is the Pi-hole base URL (no /admin path suffix for v6 API).
- If it happens only occasionally, rely on the widget's cache/retry on next page refresh.
Defensive patterns
Strategy: retry
Try / catch
stats, sid, err := fetchPiholeV6Stats(...)
if err != nil {
if errors.Is(err, errPartialContent) {
// graph/top-domains degraded but stats present: render with warning
} else {
// statsErr: fatal for this refresh; keep cached render and retry later
}
} Prevention
- Use the widget's cache duration so transient stats failures serve stale data.
- Watch for 401-wrapped causes — they indicate session/auth problems, not load.
- Keep the Pi-hole FTL service healthy; its API is single-threaded under load.
When it happens
Trigger: The main stats request (GET /api/stats with the session) returns non-2xx, times out, or returns undecodable JSON, while optional graph/top-domain goroutines may or may not have succeeded.
Common situations: Session invalidated server-side between auth and stats call; Pi-hole under load timing out; URL pointing to a path that 404s; proxy interference on /api/stats.
Related errors
- fetching session ID: %v
- checking session ID: %v
- renewing session ID: %v
- sending authentication request: %v
- reading authentication response: %v
AI-assisted analysis of glanceapp/glance@91324e8de7 (2026-08-15).
Data as JSON: /api/errors/af075833fd6cb123.
Report an issue: GitHub.