{"record":{"id":"26a75113dd55ff13","repo":"wtfutil/wtf","slug":"only-pi-hole-api-version-3-is-supported-version","errorCode":null,"errorMessage":" only Pi-hole API version 3 is supported\n version %d was detected","messagePattern":" only Pi-hole API version 3 is supported\n version (.+?) was detected","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/pihole/client.go","lineNumber":344,"sourceCode":"\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\n\tquery.Add(strings.ToLower(action), \"\")\n\tquery.Add(\"auth\", widget.settings.token)\n\n\turl.RawQuery = query.Encode()","sourceCodeStart":326,"sourceCodeEnd":362,"githubUrl":"https://github.com/wtfutil/wtf/blob/bb838c1ccb0f0f3223690df44afdec663d622881/modules/pihole/client.go#L326-L362","documentation":"Version compatibility guard in checkServer: after querying the Pi-hole API, the returned version field is not 3. The module only understands API v3, so with Pi-hole v5+ or v6 instances (which ship different API versions/endpoints) the widget refuses to proceed rather than misparse responses.","triggerScenarios":"vResp.Version != 3 in checkServer after a successful parse of the '<apiUrl>?version' response.","commonSituations":"Pi-hole was upgraded to a release exposing a newer API version, or the endpoint sits behind a proxy that alters the response, or a non-Pi-hole service happens to answer on that URL.","solutions":["Use a Pi-hole instance exposing API version 3 (or an older Pi-hole release)","Check for an updated wtfutil version supporting newer Pi-hole APIs","Pin the Pi-hole version or expose a v3-compatible endpoint proxy"],"exampleFix":"// before: unsupported Pi-hole v6 API\n// after: run a compatible Pi-hole (FTL v5.x) or upgrade the widget\n// check locally:\n// curl http://pi.hole/admin/api.php?version  -> {\"version\":3}","handlingStrategy":"validation","validationCode":"var v struct{ Version int `json:\"version\"` }\nresp, err := http.Get(apiURL + \"?version\")\nif err == nil {\n    if json.NewDecoder(resp.Body).Decode(&v) == nil && v.Version != 3 {\n        log.Printf(\"Pi-hole API version %d detected; widget needs version 3\", v.Version)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := widget.checkServer(*client, apiUrl); err != nil {\n    if strings.Contains(err.Error(), \"only Pi-hole API version 3\") {\n        log.Printf(\"upgrade/downgrade Pi-hole or the widget: %v\", err)\n    }\n}","preventionTips":["Pin Pi-hole to an FTL release exposing API version 3","Check the version endpoint after every Pi-hole upgrade","Keep the widget/library updated alongside Pi-hole major versions"],"tags":["pi-hole","api-version","compatibility"],"backgroundTag":"api-version-unsupported","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"}