{"record":{"id":"8ea3c2a938060c92","repo":"wtfutil/wtf","slug":"invalid-response-returned-from-pi-hole-server-s","errorCode":null,"errorMessage":" invalid response returned from Pi-hole Server\n %s","messagePattern":" invalid response returned from Pi-hole Server\n (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/pihole/client.go","lineNumber":340,"sourceCode":"\t}()\n\n\tif resp.StatusCode >= http.StatusBadRequest {\n\t\treturn 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 vResp struct {\n\t\tVersion int `json:\"version\"`\n\t}\n\n\tvar rBody []byte\n\n\tif rBody, err = io.ReadAll(resp.Body); err != nil {\n\t\treturn fmt.Errorf(\" Pi-hole server failed to respond\\n %s\", parseError(err))\n\t}\n\n\tif err = json.Unmarshal(rBody, &vResp); err != nil {\n\t\treturn fmt.Errorf(\" invalid response returned from Pi-hole Server\\n %s\", parseError(err))\n\t}\n\n\tif vResp.Version != 3 {\n\t\treturn fmt.Errorf(\" only Pi-hole API version 3 is supported\\n version %d was detected\", vResp.Version)\n\t}\n\n\treturn err\n}\n\nfunc (widget *Widget) adblockSwitch(action string) {\n\tvar req *http.Request\n\n\tvar url *url2.URL\n\turl, _ = url2.Parse(widget.settings.apiUrl)\n\n\tvar query url2.Values\n\tquery, _ = url2.ParseQuery(url.RawQuery)\n","sourceCodeStart":322,"sourceCodeEnd":358,"githubUrl":"https://github.com/wtfutil/wtf/blob/bb838c1ccb0f0f3223690df44afdec663d622881/modules/pihole/client.go#L322-L358","documentation":"After reading the body, checkServer unmarshals it into a struct expecting {\"version\": <int>}. If the body is not valid JSON in that shape, the library reports an invalid response from the Pi-hole server.","triggerScenarios":"json.Unmarshal(rBody, &vResp) fails in checkServer — the version endpoint returned non-JSON or JSON not matching {version:int}.","commonSituations":"apiUrl points at an HTML dashboard or login page, a Pi-hole v6 (new API) returns a different JSON envelope, or the response is a string like 'error' from a proxy.","solutions":["Point apiUrl at admin/api.php of a Pi-hole whose API returns the classic {\"version\":3} payload","Curl '<apiUrl>?version' and verify the body is JSON with a numeric version field","If running Pi-hole v6, downgrade expectations or use a widget version supporting the new API"],"exampleFix":"// before: HTML login page returned\n// after: ensure auth token configured so JSON is returned\napiUrl: http://pi.hole/admin/api.php\nauthToken: <correct-token>","handlingStrategy":"validation","validationCode":"resp, err := http.Get(apiURL + \"?version\")\nif err == nil {\n    body, _ := io.ReadAll(io.LimitReader(resp.Body, 256))\n    if !json.Valid(body) {\n        log.Printf(\"endpoint returned non-JSON (likely HTML/auth page): %.80s\", body)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := widget.checkServer(*client, apiUrl); err != nil {\n    if strings.Contains(err.Error(), \"invalid response returned\") {\n        log.Printf(\"unexpected payload from Pi-hole, verify version/schema: %v\", err)\n    }\n}","preventionTips":["Curl '<apiUrl>?version' and confirm the body is {\"version\":3}-style JSON","Set a valid API token so HTML auth pages are never returned","Account for Pi-hole major upgrades that change the API envelope"],"tags":["json","pi-hole","parsing","api-version"],"backgroundTag":"unexpected-response-schema","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"}