{"record":{"id":"f6e2429119af2b24","repo":"wtfutil/wtf","slug":"failed-to-retrieve-top-items-check-provided-api","errorCode":null,"errorMessage":" failed to retrieve top items: check provided api URL and token\n %s","messagePattern":" failed to retrieve top items: check provided api URL and token\n (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/pihole/client.go","lineNumber":160,"sourceCode":"\t\treturn ti, fmt.Errorf(\" failed to connect to Pi-hole server\\n %s\", parseError(err))\n\t}\n\n\tdefer func() {\n\t\tif closeErr := resp.Body.Close(); closeErr != nil {\n\t\t\treturn\n\t\t}\n\t}()\n\n\tif resp.StatusCode >= http.StatusBadRequest {\n\t\treturn ti, fmt.Errorf(\" failed to retrieve version from Pi-hole server\\n http status code: %d\",\n\t\t\tresp.StatusCode)\n\t}\n\n\tvar rBody []byte\n\n\trBody, err = io.ReadAll(resp.Body)\n\tif err = json.Unmarshal(rBody, &ti); err != nil {\n\t\treturn ti, fmt.Errorf(\" failed to retrieve top items: check provided api URL and token\\n %s\",\n\t\t\tparseError(err))\n\t}\n\n\treturn ti, err\n}\n\ntype TopClients struct {\n\tTopSources map[string]int `json:\"top_sources\"`\n}\n\n// parseError removes any token from output and ensures a non-nil response\nfunc parseError(err error) string {\n\tif err == nil {\n\t\treturn \"unknown error\"\n\t}\n\n\tvar re = regexp.MustCompile(`auth=[a-zA-Z0-9]*`)\n","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/wtfutil/wtf/blob/bb838c1ccb0f0f3223690df44afdec663d622881/modules/pihole/client.go#L142-L178","documentation":"getTopItems in modules/pihole/client.go wraps a json.Unmarshal failure while decoding the topItems response body into the TopItems struct. The library throws it because the server returned a body that is not JSON of the expected shape (note the code also ignores io.ReadAll's error here).","triggerScenarios":"In getTopItems (via getTopItemsView), json.Unmarshal(rBody, &ti) fails: response is HTML, empty, an auth-error JSON object, or a Pi-hole API version whose topItems schema differs from the TopItems struct.","commonSituations":"Invalid auth token returning an auth error payload; Pi-hole v6 API returning a different JSON schema than this legacy client expects; an HTML error page from a reverse proxy; empty body due to API parameter mismatch.","solutions":["Curl the exact request URL (with auth and topItems params) and inspect the raw body to see what is actually returned.","Fix settings.token so Pi-hole returns real topItems data instead of an auth error.","Check your Pi-hole version; for v6, update the client/structs to match the new API schema or use a compatible client version.","Remove any proxy that injects HTML pages into API responses."],"exampleFix":"// before\nsettings.token = \"\" // auth error JSON returned\n// after\nsettings.token = os.Getenv(\"PIHOLE_WEBPASSWORD\")","handlingStrategy":"try-catch","validationCode":"resp, err := http.Get(settings.apiUrl + \"?auth=\" + settings.token + \"&topItems=10\")\nif err == nil {\n    body, _ := io.ReadAll(resp.Body)\n    var probe map[string]json.RawMessage\n    if json.Unmarshal(body, &probe) != nil {\n        return errors.New(\"topItems endpoint did not return expected JSON\")\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := client.GetTopItemsView(ctx); err != nil {\n    if strings.Contains(err.Error(), \"failed to retrieve top items\") {\n        log.Printf(\"topItems response not parseable — check token and Pi-hole version: %v\", err)\n        return\n    }\n    return err\n}","preventionTips":["Curl the full topItems request and confirm the JSON schema matches the client's TopItems struct.","Keep the client library version aligned with your Pi-hole major version.","Verify the token is valid so the API returns data, not an auth-error payload.","Ensure no proxy injects HTML into API responses."],"tags":["json","unmarshal","pihole","http-response"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"bb838c1ccb0f0f3223690df44afdec663d622881","analyzedAt":"2026-09-03T17:02:45.030Z","contentChangedAt":"2026-09-03T17:02:45.030Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}