{"record":{"id":"ad22e8083711e106","repo":"kopia/kopia","slug":"unable-to-parse-json-response","errorCode":null,"errorMessage":"unable to parse JSON response","messagePattern":"unable to parse JSON response","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/apiclient/apiclient.go","lineNumber":190,"sourceCode":"\nfunc decodeResponse(resp *http.Response, respPayload any) error {\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn HTTPStatusError{resp.StatusCode, respToErrorMessage(resp)}\n\t}\n\n\tif respPayload == nil {\n\t\treturn nil\n\t}\n\n\tif b, ok := respPayload.(*[]byte); ok {\n\t\tv, err := io.ReadAll(resp.Body)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"unable to read response\")\n\t\t}\n\n\t\t*b = v\n\t} else if err := json.NewDecoder(resp.Body).Decode(respPayload); err != nil {\n\t\treturn errors.Wrap(err, \"unable to parse JSON response\")\n\t}\n\n\treturn nil\n}\n\n// Options encapsulates all optional parameters for KopiaAPIClient.\ntype Options struct {\n\tBaseURL string\n\n\tUsername string\n\tPassword string\n\n\tTrustedServerCertificateFingerprint string\n\n\tLogRequests bool\n}\n\n// NewKopiaAPIClient creates a client for connecting to Kopia HTTP API.","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/kopia/kopia/blob/82495e54b584c1ef6073c9e1be048f57f8aef078/internal/apiclient/apiclient.go#L172-L208","documentation":"decodeResponse decodes the response body as JSON into the caller-provided pointer. This error means the body is not valid JSON or does not decode into the target type — commonly because the server returned an HTML error page, an empty body, or the caller's target struct does not match the actual payload.","triggerScenarios":"Any API call whose expected respPayload is a JSON struct while the server returns non-JSON: an HTML 502/503 page from a proxy, plain-text error, empty 200 body, or a schema mismatch (field type changed).","commonSituations":"Hitting the wrong port so a different service answers; proxy error pages; Kopia server version older/newer than the client DTOs expect; unauthenticated captive-portal or login page responses.","solutions":["Dump the raw response body/status to see what was actually returned","Verify the request is reaching the Kopia API server, not a proxy or different service","Check server/client version compatibility of the API DTOs","If the body may legitimately be empty, use a *[]byte target instead","Confirm authentication succeeded — some servers return non-JSON auth errors"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"resp, err := http.Get(url)\nif err != nil { return err }\nct := resp.Header.Get(\"Content-Type\")\nif !strings.HasPrefix(ct, \"application/json\") {\n    return fmt.Errorf(\"expected JSON, got %q status %d\", ct, resp.StatusCode)\n}","typeGuard":"func isJSONResponse(h http.Header) bool {\n    return strings.HasPrefix(h.Get(\"Content-Type\"), \"application/json\")\n}","tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"parse JSON response\") {\n    // log status + raw body snippet for diagnosis\n}","preventionTips":["Check Content-Type/status before decoding","Confirm you are pointing at the Kopia API, not a proxy","Pin client/server API versions together","Use *[]byte targets when the body may be non-JSON"],"tags":["json","http","response-parsing"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"82495e54b584c1ef6073c9e1be048f57f8aef078","analyzedAt":"2026-09-07T20:35:21.689Z","contentChangedAt":"2026-09-07T20:35:21.689Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}