{"record":{"id":"1cd3b02798b8fe66","repo":"Netflix/chaosmonkey","slug":"json-unmarshal-failed-1cd3b0","errorCode":null,"errorMessage":"json unmarshal failed","messagePattern":"json unmarshal failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"spinnaker/spinnaker.go","lineNumber":528,"sourceCode":"\tif err != nil {\n\t\treturn ac, errors.Wrapf(err, \"http get failed at %s\", url)\n\t}\n\n\tdefer func() {\n\t\tif cerr := resp.Body.Close(); cerr != nil && err == nil {\n\t\t\terr = errors.Wrap(err, fmt.Sprintf(\"body close failed at %s\", url))\n\t\t}\n\t}()\n\n\tbody, err := ioutil.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn ac, errors.Wrapf(err, \"body read failed at %s\", url)\n\t}\n\n\tvar accounts []account\n\terr = json.Unmarshal(body, &accounts)\n\tif err != nil {\n\t\treturn ac, errors.Wrap(err, \"json unmarshal failed\")\n\t}\n\tstatusKO := resp.StatusCode != http.StatusOK\n\n\t// Finally find account\n\tfor _, a := range accounts {\n\t\tif a.Name != name {\n\t\t\tcontinue\n\t\t}\n\t\tif statusKO {\n\t\t\tif a.Error == \"\" {\n\t\t\t\treturn ac, errors.Errorf(\"unexpected status code: %d. body: %s\", resp.StatusCode, body)\n\t\t\t}\n\n\t\t\treturn ac, errors.Errorf(\"unexpected status code: %d. error: %s\", resp.StatusCode, a.Error)\n\t\t}\n\n\t\treturn a, nil\n\t}","sourceCodeStart":510,"sourceCodeEnd":546,"githubUrl":"https://github.com/Netflix/chaosmonkey/blob/eaa28fb761c0ebe8644d1333e5d164e9cc3071e9/spinnaker/spinnaker.go#L510-L546","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Print the raw body to see what was actually returned before unmarshaling.","Fix authentication so the request is not redirected to an HTML login page.","Check proxy/gateway configuration for intercepted error responses.","Verify the Spinnaker version's /accounts schema still matches {cloudProvider,name,error} and update the library if it changed.","Curl the endpoint and validate the JSON array structure."],"exampleFix":"// before\nvar accounts []account\nerr = json.Unmarshal(body, &accounts)\n// after (diagnose)\nif err != nil {\n    return ac, errors.Wrapf(err, \"json unmarshal failed; body: %s\", string(body))\n}","handlingStrategy":"validation","validationCode":"// probe that /accounts returns valid JSON before use\nresp, err := httpClient.Get(accountsURL)\nif err != nil {\n    return err\n}\nbody, _ := ioutil.ReadAll(resp.Body)\nresp.Body.Close()\nct := resp.Header.Get(\"Content-Type\")\nif !strings.Contains(ct, \"application/json\") {\n    return fmt.Errorf(\"/accounts returned %q, expected JSON — check auth/proxy\", ct)\n}\nvar probe []map[string]interface{}\nif err := json.Unmarshal(body, &probe); err != nil {\n    return fmt.Errorf(\"/accounts payload not a JSON array: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"// Go: log the offending body when unmarshal fails\n_, err := s.CloudProvider(account)\nif err != nil && strings.Contains(err.Error(), \"json unmarshal failed\") {\n    log.Printf(\"spinnaker /accounts returned non-JSON payload: %+v — check auth redirects, proxy error pages, or API schema changes\", err)\n}\nreturn err","preventionTips":["Ensure credentials are attached so /accounts never returns a login page","Check Content-Type before parsing","Pin Spinnaker versions compatible with the client's schema","Curl /accounts when diagnosing to inspect the raw payload"],"tags":["json","parsing","api-schema","spinnaker"],"backgroundTag":"schema-validation-failed","analyzedSha":"eaa28fb761c0ebe8644d1333e5d164e9cc3071e9","analyzedAt":"2026-09-03T17:04:39.020Z","contentChangedAt":"2026-09-03T17:04:39.020Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}