anomalyco/sst · error

failed to parse API response: %v

Error message

failed to parse API response: %v

What it means

This error is returned by createOrUpdateRecord when the JSON body of the Cloudflare DNS-record API response cannot be unmarshaled into the expected CloudflareResponse struct. The library assumes the endpoint returns well-formed JSON matching its schema, so a non-JSON or structurally different body is treated as an unparseable response rather than an API error.

Source

Thrown at pkg/server/resource/cloudflare-dns-record.go:152

	
	// Define response structures based on Cloudflare API docs
	type CloudflareError struct {
		Code    int    `json:"code"`
		Message string `json:"message"`
	}

	type CloudflareResponse struct {
		Success  bool              `json:"success"`
		Errors   []CloudflareError `json:"errors"`
		Messages []string          `json:"messages"`
		Result   struct {
			Id string `json:"id"`
		} `json:"result"`
	}

	var apiResponse CloudflareResponse
	if err := json.Unmarshal(body, &apiResponse); err != nil {
		return "", fmt.Errorf("failed to parse API response: %v", err)
	}

	// Check if the response was successful
	if resp.StatusCode < 200 || resp.StatusCode >= 300 || !apiResponse.Success {
		// Check for "already exists" in error messages
		if len(apiResponse.Errors) > 0 {
			for _, cfError := range apiResponse.Errors {
				// Check if message contains "already exists" regardless of error code
				if strings.Contains(strings.ToLower(cfError.Message), "already exists") {
					return "existing-record", nil
				}
			}
		}
		
		// If not an "already exists" error, return the error information
		errorMsgs := []string{}
		for _, cfError := range apiResponse.Errors {
			errorMsgs = append(errorMsgs, fmt.Sprintf("%s", cfError.Message))

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Print/log the raw response body and status code to see what was actually returned
  2. Verify the API token is valid and scoped to the zone: curl -H "Authorization: Bearer $TOKEN" https://api.cloudflare.com/client/v4/user/tokens/verify
  3. Retry later if it's an HTML challenge/rate-limit page; reduce request frequency
  4. Check for a proxy/firewall intercepting traffic to api.cloudflare.com
  5. If the API response shape changed, update the CloudflareResponse struct to match

Example fix

// before
var apiResponse CloudflareResponse
if err := json.Unmarshal(body, &apiResponse); err != nil {
    return "", fmt.Errorf("failed to parse API response: %v", err)
}
// after — include body/status for diagnosis
var apiResponse CloudflareResponse
if err := json.Unmarshal(body, &apiResponse); err != nil {
    return "", fmt.Errorf("failed to parse API response (status %d): %v: body: %s", resp.StatusCode, err, string(body))
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: verify the token before creating records
tokenOK := verifyCloudflareToken(apiToken) // calls /user/tokens/verify and checks JSON success==true

Try / catch

id, err := record.Create(input, &out)
if err != nil {
    if strings.Contains(err.Error(), "failed to parse API response") {
        // non-JSON body: log status/body, back off, retry
        return fmt.Errorf("cloudflare returned a non-JSON response; check token/proxy and retry: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: The POST to the Cloudflare DNS record endpoint returns a body that is not the expected JSON envelope — e.g. an HTML error page from a proxy/firewall, a truncated or empty body, an HTML Cloudflare challenge/rate-limit page (status 503/1015), or JSON whose types don't fit the struct (e.g. result as a string or errors entries as strings).

Common situations: Invalid or expired API token causing an HTML login redirect; corporate proxy or Cloudflare WAF returning an HTML block page; network middleware returning plain text; Cloudflare API version change altering the response shape; request hitting an interposed captive portal.

Understand the failure class

Related errors


AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30). Data as JSON: /api/errors/ae79c89080bb4733. Report an issue: GitHub.