googleapis/mcp-toolbox · error
failed to unmarshal response: %v
Error message
failed to unmarshal response: %v
What it means
doLogin fails to parse the body returned by the Dgraph /login endpoint as JSON into the expected {data:{accessJWT,refreshJWT}} shape. This means the server (or an intermediary) responded with malformed JSON, an empty body, or non-JSON content such as an HTML error page. The underlying parse error is wrapped with %v.
Source
Thrown at internal/sources/dgraph/dgraph.go:327
!strings.Contains(err.Error(), "unable to authenticate the refresh token") {
return hc.loginWithToken()
}
return err
}
if err := checkError(resp); err != nil {
return err
}
var r struct {
Data struct {
AccessJWT string `json:"accessJWT"`
RefreshJWT string `json:"refreshJWT"`
} `json:"data"`
}
if err := json.Unmarshal(resp, &r); err != nil {
return fmt.Errorf("failed to unmarshal response: %v", err)
}
if r.Data.AccessJWT == "" {
return fmt.Errorf("no access JWT found in the response")
}
if r.Data.RefreshJWT == "" {
return fmt.Errorf("no refresh JWT found in the response")
}
hc.AccessJwt = r.Data.AccessJWT
hc.RefreshToken = r.Data.RefreshJWT
return nil
}
func (hc *DgraphClient) healthCheck() error {
url, err := getUrl(hc.baseUrl, "/health", nil)
if err != nil {
return errView on GitHub (pinned to 8cc6e09de2)
Solutions
- Verify hc.baseUrl points to Dgraph Alpha's HTTP port (default 8080), not the gRPC port 9080.
- Log or print the raw response body to see whether it is HTML, empty, or JSON with an unexpected shape.
- Bypass intermediaries: curl the /login endpoint directly to rule out proxy/load-balancer error pages.
- Confirm the Dgraph version's /login response uses {"data":{"accessJWT":...,"refreshJWT":...}} and update the parsing struct if not.
- Check TLS configuration if connecting through HTTPS — certificate errors can yield non-JSON responses.
Example fix
// debugging: inspect what /login actually returned
fmt.Printf("login response: %s\n", string(resp))
// before
// (no diagnostics — opaque unmarshal failure)
// after
// raw body is logged before unmarshal, revealing HTML proxy pages or empty bodies Defensive patterns
Strategy: try-catch
Validate before calling
// preflight: ensure the endpoint speaks JSON before logging in
resp, err := http.Get(baseURL + "/health")
if err != nil || resp.StatusCode != 200 {
return fmt.Errorf("dgraph endpoint not reachable/healthy at %s", baseURL)
} Type guard
func isJSONResponse(body []byte) bool {
t := bytes.TrimSpace(body)
return len(t) > 0 && (t[0] == '{' || t[0] == '[')
} Try / catch
if err := doLogin(...); err != nil {
if strings.Contains(err.Error(), "failed to unmarshal response") {
log.Printf("non-JSON login response; verify baseURL port (8080 vs 9080) and proxies: %v", err)
return
}
} Prevention
- Point baseURL at Dgraph Alpha's HTTP port (default 8080), never the gRPC port 9080.
- Log the raw login response body when debugging to spot HTML proxy error pages.
- Run a /health preflight check before the first login call.
- Bypass or configure load balancers so they do not serve HTML error pages to API clients.
- Pin and test against the Dgraph version whose login response schema you parse.
When it happens
Trigger: json.Unmarshal(resp, &r) errors after the login POST completes — response body is empty, truncated, HTML (proxy/load-balancer error page), or JSON with a different structure than expected.
Common situations: Wrong port (hitting Dgraph Alpha's gRPC port 9080 over HTTP), a reverse proxy or API gateway returning an HTML 502/403 page, TLS termination issues, or a Dgraph version whose login response shape differs.
Understand the failure class
Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.
Related errors
- failed to marshal credentials: %v
- failed to unmarshal json: %v
- could not unmarshal response as json: %w
- failed to unmarshal operation JSON to map: %w
- error parsing JSON: %v
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/5c416057d897793c.
Report an issue: GitHub.