Netflix/chaosmonkey · error

json unmarshal failed

Error message

json unmarshal failed

What it means

The internal Spinnaker.account function throws this when json.Unmarshal cannot parse the /accounts response into []account. The expected schema is a JSON array of objects with cloudProvider, name, and error fields. It means the server response is not the expected account list — often an HTML error page, empty body, or a changed API payload.

Source

Thrown at spinnaker/spinnaker.go:528

	if err != nil {
		return ac, errors.Wrapf(err, "http get failed at %s", url)
	}

	defer func() {
		if cerr := resp.Body.Close(); cerr != nil && err == nil {
			err = errors.Wrap(err, fmt.Sprintf("body close failed at %s", url))
		}
	}()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return ac, errors.Wrapf(err, "body read failed at %s", url)
	}

	var accounts []account
	err = json.Unmarshal(body, &accounts)
	if err != nil {
		return ac, errors.Wrap(err, "json unmarshal failed")
	}
	statusKO := resp.StatusCode != http.StatusOK

	// Finally find account
	for _, a := range accounts {
		if a.Name != name {
			continue
		}
		if statusKO {
			if a.Error == "" {
				return ac, errors.Errorf("unexpected status code: %d. body: %s", resp.StatusCode, body)
			}

			return ac, errors.Errorf("unexpected status code: %d. error: %s", resp.StatusCode, a.Error)
		}

		return a, nil
	}

View on GitHub (pinned to eaa28fb761)

Solutions

  1. Print the raw body to see what was actually returned before unmarshaling.
  2. Fix authentication so the request is not redirected to an HTML login page.
  3. Check proxy/gateway configuration for intercepted error responses.
  4. Verify the Spinnaker version's /accounts schema still matches {cloudProvider,name,error} and update the library if it changed.
  5. Curl the endpoint and validate the JSON array structure.

Example fix

// before
var accounts []account
err = json.Unmarshal(body, &accounts)
// after (diagnose)
if err != nil {
    return ac, errors.Wrapf(err, "json unmarshal failed; body: %s", string(body))
}
Defensive patterns

Strategy: validation

Validate before calling

// probe that /accounts returns valid JSON before use
resp, err := httpClient.Get(accountsURL)
if err != nil {
    return err
}
body, _ := ioutil.ReadAll(resp.Body)
resp.Body.Close()
ct := resp.Header.Get("Content-Type")
if !strings.Contains(ct, "application/json") {
    return fmt.Errorf("/accounts returned %q, expected JSON — check auth/proxy", ct)
}
var probe []map[string]interface{}
if err := json.Unmarshal(body, &probe); err != nil {
    return fmt.Errorf("/accounts payload not a JSON array: %w", err)
}

Try / catch

// Go: log the offending body when unmarshal fails
_, err := s.CloudProvider(account)
if err != nil && strings.Contains(err.Error(), "json unmarshal failed") {
    log.Printf("spinnaker /accounts returned non-JSON payload: %+v — check auth redirects, proxy error pages, or API schema changes", err)
}
return err

Prevention

When it happens

Trigger: Calling CloudProvider/GetApp when the /accounts endpoint returns non-JSON: an auth/login redirect page, a proxy error page, an empty body with 200, or a Spinnaker version whose payload shape differs.

Common situations: Expired session redirected to a login page with 200; misconfigured reverse proxy returning its own error page; Spinnaker API upgrade renaming fields; hitting the wrong endpoint path.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of Netflix/chaosmonkey@eaa28fb761 (2026-09-03). Data as JSON: /api/errors/1cd3b02798b8fe66. Report an issue: GitHub.