kopia/kopia · error
unable to parse JSON response
Error message
unable to parse JSON response
What it means
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.
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
Defensive patterns
Strategy: type-guard
Validate before calling
resp, err := http.Get(url)
if err != nil { return err }
ct := resp.Header.Get("Content-Type")
if !strings.HasPrefix(ct, "application/json") {
return fmt.Errorf("expected JSON, got %q status %d", ct, resp.StatusCode)
} Type guard
func isJSONResponse(h http.Header) bool {
return strings.HasPrefix(h.Get("Content-Type"), "application/json")
} Try / catch
if err != nil && strings.Contains(err.Error(), "parse JSON response") {
// log status + raw body snippet for diagnosis
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- invalid GitHub API response
- access denied
- Access denied.
- can't marshal blobCfgBlob to JSON
- can't marshal format to JSON
AI-assisted analysis of kopia/kopia@82495e54b5 (2026-09-07).
Data as JSON: /api/errors/ad22e8083711e106.
Report an issue: GitHub.
Appendix: source
Thrown at internal/apiclient/apiclient.go:190
func decodeResponse(resp *http.Response, respPayload any) error {
if resp.StatusCode != http.StatusOK {
return HTTPStatusError{resp.StatusCode, respToErrorMessage(resp)}
}
if respPayload == nil {
return nil
}
if b, ok := respPayload.(*[]byte); ok {
v, err := io.ReadAll(resp.Body)
if err != nil {
return errors.Wrap(err, "unable to read response")
}
*b = v
} else if err := json.NewDecoder(resp.Body).Decode(respPayload); err != nil {
return errors.Wrap(err, "unable to parse JSON response")
}
return nil
}
// Options encapsulates all optional parameters for KopiaAPIClient.
type Options struct {
BaseURL string
Username string
Password string
TrustedServerCertificateFingerprint string
LogRequests bool
}
// NewKopiaAPIClient creates a client for connecting to Kopia HTTP API.View on GitHub (pinned to 82495e54b5)