{"record":{"id":"3fadda3b1cdc745c","repo":"hasura/graphql-engine","slug":"decoding-api-response-failed-for-v","errorCode":null,"errorMessage":"decoding API response failed for: %v","messagePattern":"decoding API response failed for: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/internal/hasura/v1version/version.go","lineNumber":50,"sourceCode":"\tif err != nil {\n\t\treturn nil, errors.E(op, err)\n\t}\n\n\tif resp.StatusCode != http.StatusOK {\n\t\tif b.Len() > 0 {\n\t\t\treturn nil, errors.E(op, errors.KindHasuraAPI, b.String())\n\t\t} else {\n\t\t\treturn nil, errors.E(\n\t\t\t\top,\n\t\t\t\terrors.KindHasuraAPI,\n\t\t\t\tfmt.Errorf(\"API request to %v failed, code: %v\", c.path, resp.StatusCode),\n\t\t\t)\n\t\t}\n\t}\n\n\to := new(hasura.V1VersionResponse)\n\tif err := json.NewDecoder(b).Decode(o); err != nil {\n\t\treturn nil, errors.E(op, fmt.Errorf(\"decoding API response failed for: %v\", c.path))\n\t}\n\n\treturn o, nil\n}\n\nfunc (c *Client) send(body any, responseBodyWriter io.Writer) (*httpc.Response, error) {\n\tvar op errors.Op = \"v1version.Client.send\"\n\n\treq, err := c.NewRequest(http.MethodGet, c.path, body)\n\tif err != nil {\n\t\treturn nil, errors.E(op, err)\n\t}\n\n\tresp, err := c.LockAndDo(context.Background(), req, responseBodyWriter)\n\tif err != nil {\n\t\treturn nil, errors.E(op, err)\n\t}\n","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/hasura/graphql-engine/blob/724551b9ae87845594ef0408cff0e50eb6c90dc5/cli/internal/hasura/v1version/version.go#L32-L68","documentation":"Returned by GetVersion when the response body from /v1/version cannot be decoded into hasura.V1VersionResponse (a JSON object with a version field). This means the server returned HTTP 200 but the payload was not the expected JSON shape — typically HTML or an empty/garbled body.","triggerScenarios":"The /v1/version URL returns 200 with HTML (a SPA, login page, or catch-all route), an API gateway that rewrites responses, a server that returns an empty body, or a proxy serving a status page on all paths.","commonSituations":"Endpoint pointed at a domain where a web app catches all routes with 200 HTML, misconfigured ingress rewrite rules, or a non-Hasura service listening on the target port.","solutions":["Curl the URL directly and inspect the body: curl <endpoint>/v1/version — if it's HTML, the endpoint is wrong","Point the CLI at the actual Hasura server root URL","Fix ingress/proxy rules so /v1/version is passed through to Hasura unmodified"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"resp, err := http.Get(endpoint + \"/v1/version\")\nif err == nil {\n\tdefer resp.Body.Close()\n\tb, _ := io.ReadAll(resp.Body)\n\tvar probe struct{ Version string `json:\"version\"` }\n\tif json.Unmarshal(b, &probe) != nil || probe.Version == \"\" {\n\t\t// endpoint is not serving the Hasura version JSON; fix URL/proxy\n\t}\n}","typeGuard":null,"tryCatchPattern":"v, err := client.GetVersion()\nif err != nil {\n\tif strings.Contains(err.Error(), \"decoding API response failed\") {\n\t\t// server returned 200 with non-JSON (HTML/empty): endpoint or proxy misconfigured\n\t}\n\treturn err\n}","preventionTips":["Verify the endpoint returns JSON, not a catch-all HTML page","Avoid ingresses that rewrite /v1/version","Smoke-test the URL with curl -i after infra changes"],"tags":["hasura","json-decode","version-endpoint","proxy"],"backgroundTag":"json-decode-response-failed","analyzedSha":"724551b9ae87845594ef0408cff0e50eb6c90dc5","analyzedAt":"2026-08-28T07:32:55.105Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}