VictoriaMetrics/VictoriaMetrics · error

cannot unmarshal response from %s: %w

Error message

cannot unmarshal response from %s: %w

What it means

Returned by getVPSDetails when the JSON body from GET /vps/{serviceName} cannot be unmarshaled into the virtualPrivateServer struct. The API responded, but with data not matching the expected schema (fields/types differ). Cause is wrapped with %w.

Source

Thrown at lib/promscrape/discovery/ovhcloud/vps.go:125

	}
	return ms, nil
}

// getVPSDetails get properties of a VPS.
// Also see: https://eu.api.ovh.com/console/#/vps/%7BserviceName%7D~GET
func getVPSDetails(cfg *apiConfig, vpsName string) (*virtualPrivateServer, error) {
	// get properties.
	reqPath := path.Join("/vps", url.QueryEscape(vpsName))
	resp, err := cfg.client.GetAPIResponseWithReqParams(reqPath, func(request *http.Request) {
		request.Header, _ = getAuthHeaders(cfg, request.Header, cfg.client.APIServer(), reqPath)
	})
	if err != nil {
		return nil, fmt.Errorf("cannot process %s: %w", reqPath, err)
	}

	var vpsDetails virtualPrivateServer
	if err = json.Unmarshal(resp, &vpsDetails); err != nil {
		return nil, fmt.Errorf("cannot unmarshal response from %s: %w", reqPath, err)
	}

	// get IPs for this vps.
	// e.g. ["139.99.154.111","2402:1f00:8100:401::bb6"]
	// Also see: https://eu.api.ovh.com/console/#/vps/%7BserviceName%7D/ips~GET
	reqPath = path.Join(reqPath, "ips")
	resp, err = cfg.client.GetAPIResponseWithReqParams(reqPath, func(request *http.Request) {
		request.Header, _ = getAuthHeaders(cfg, request.Header, cfg.client.APIServer(), reqPath)
	})
	if err != nil {
		return nil, fmt.Errorf("cannot process %s: %w", reqPath, err)
	}

	var ips []string
	if err = json.Unmarshal(resp, &ips); err != nil {
		return nil, fmt.Errorf("cannot unmarshal response from %s: %w", reqPath, err)
	}

View on GitHub (pinned to 5079fb58f1)

Solutions

  1. Capture and inspect the raw response body to see the actual payload
  2. Confirm the request is hitting the official OVH endpoint (not a proxy returning errors as HTML)
  3. Check the library version against recent OVH /vps API schema changes; upgrade the library if the API evolved
  4. Retry after confirming OVH API health if it was a transient malformed response
Defensive patterns

Strategy: type-guard

Validate before calling

// verify payload shape before unmarshal
if len(resp) > 0 && resp[0] != '{' {
    return fmt.Errorf("unexpected /vps payload, want JSON object: %q", resp[:min(200, len(resp))])
}

Type guard

func looksLikeVPSObject(b []byte) bool {
    var m map[string]json.RawMessage
    return json.Unmarshal(b, &m) == nil && len(m) > 0
}

Try / catch

// log body on schema mismatch
if err := json.Unmarshal(resp, &vpsDetails); err != nil {
    log.Printf("vps schema mismatch: %v; body=%s", err, string(resp))
    return nil, err
}

Prevention

When it happens

Trigger: json.Unmarshal(resp, &vpsDetails) fails: body is an OVH error object, HTML from a proxy, or a schema mismatch (e.g. a field type changed in the OVH API that no longer matches the struct).

Common situations: OVH API schema evolution breaking the struct; error payload returned with success status; proxy/WAF injecting HTML; truncated responses on flaky connections.

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.

Related errors


AI-assisted analysis of VictoriaMetrics/VictoriaMetrics@5079fb58f1 (2026-09-03). Data as JSON: /api/errors/628e447345fa468f. Report an issue: GitHub.