{"record":{"id":"3b1b30baf659556e","repo":"Netflix/chaosmonkey","slug":"json-unmarshal-failed-body-s","errorCode":null,"errorMessage":"json unmarshal failed, body: %s","messagePattern":"json unmarshal failed, body: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"spinnaker/terminator.go","lineNumber":187,"sourceCode":"\t\t\t\t\t\"state\": \"Up\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"instanceId\": \"55fe33ab-5b66-450a-85f7-f3129806b87f\",\n\t\t\t\t\t\"titusTaskId\": \"Titus-123456-worker-0-0\",\n\t\t\t\t\t...\n\t\t\t\t}\n\t\t\t],\n\t\t}\n\t*/\n\n\tvar fields struct {\n\t\tHealth []map[string]interface{} `json:\"health\"`\n\t\tError  string                   `json:\"error\"`\n\t}\n\n\terr = json.Unmarshal(body, &fields)\n\tif err != nil {\n\t\treturn \"\", errors.Wrap(err, fmt.Sprintf(\"json unmarshal failed, body: %s\", body))\n\t}\n\n\tif resp.StatusCode != http.StatusOK {\n\t\tif fields.Error == \"\" {\n\t\t\treturn \"\", fmt.Errorf(\"unexpected status code: %d. body: %s\", resp.StatusCode, body)\n\t\t}\n\n\t\treturn \"\", fmt.Errorf(\"unexpected status code: %d. error: %s\", resp.StatusCode, fields.Error)\n\t}\n\n\t// In some cases, an instance may be missing health information.\n\t// We just return a blank otherID in that case\n\tif len(fields.Health) < 2 {\n\t\treturn \"\", nil\n\t}\n\n\totherID, ok := fields.Health[1][\"instanceId\"].(string)\n\tif !ok {","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/Netflix/chaosmonkey/blob/eaa28fb761c0ebe8644d1333e5d164e9cc3071e9/spinnaker/terminator.go#L169-L205","documentation":"OtherID throws this when json.Unmarshal cannot decode the instance endpoint response into the expected struct with Health and Error fields. The request completed and the body was read, but the body is not the expected JSON document. The failing body is embedded verbatim in the message so you can see exactly what Spinnaker returned.","triggerScenarios":"GET <spinnaker-api>/<account>/<region>/<instanceId> returns a body that is not valid JSON for the expected schema: an HTML error/login page from a proxy, an empty body, gzip/encoding garbage, or a Spinnaker response whose instance payload differs from the expected {health: [...]} shape.","commonSituations":"Instance already terminated so Gate returns an unexpected document; an SSO/auth proxy intercepting the GET with its own HTML response; content-encoding mismatches (client not handling gzip); Spinnaker version changes altering the instance response schema; wrong endpoint URL hitting a non-Gate service.","solutions":["Inspect the body embedded in the error message to see what was actually returned.","Curl the same URL with the same credentials to reproduce and inspect headers (content-type, content-encoding).","Check whether the instance still exists in Spinnaker/Titus; a terminated instance may yield a non-JSON error page.","Verify no auth/SSO proxy is intercepting the request and that the endpoint URL targets Gate's instance API.","Confirm your Spinnaker version's instance response matches the library's expected schema and update the library or Spinnaker accordingly."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"resp, err := client.Get(instanceURL)\nif err != nil {\n\treturn err\n}\nbody, _ := ioutil.ReadAll(resp.Body)\nif !json.Valid(body) {\n\treturn fmt.Errorf(\"non-JSON from %s (content-type: %s): %.200s\", instanceURL, resp.Header.Get(\"Content-Type\"), body)\n}\nvar probe struct{ Health []json.RawMessage }\nif err := json.Unmarshal(body, &probe); err != nil {\n\treturn fmt.Errorf(\"unexpected instance schema: %v\", err)\n}","typeGuard":"func looksLikeInstanceDoc(body []byte) bool {\n\tvar probe struct{ Health []map[string]interface{} }\n\treturn json.Unmarshal(body, &probe) == nil\n}","tryCatchPattern":"err = json.Unmarshal(body, &fields)\nif err != nil {\n\tlog.Printf(\"json unmarshal failed for %s, body: %.500s\", url, body)\n\treturn \"\", errors.Wrap(err, fmt.Sprintf(\"json unmarshal failed, body: %s\", body))\n}","preventionTips":["Check the instance still exists in Spinnaker before querying; terminated instances return unexpected documents","Verify content-encoding handling (gzip) matches between client and Gate","Ensure no auth/SSO proxy intercepts instance GETs with HTML responses","Log a truncated body snippet on unmarshal failure for fast diagnosis"],"tags":["go","json","spinnaker","titus","api-contract"],"backgroundTag":"json-unmarshal-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"}