{"record":{"id":"2102e7bb26129b34","repo":"Netflix/chaosmonkey","slug":"json-unmarshal-failed","errorCode":null,"errorMessage":"json unmarshal failed","messagePattern":"json unmarshal failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"spinnaker/fromjson.go","lineNumber":98,"sourceCode":"//\t \t  \t\"stack\": \"foo\",\n//\t \t  \t\"detail\": \"bar\"\n//\t \t  \t}\n//\t \t  ],\n//\t \t  \"whitelist\": [\n//\t \t  \t{\n//\t \t  \t\"account\": \"test\",\n//\t \t  \t\"stack\": \"*\",\n//\t \t  \t\"region\": \"*\",\n//\t \t  \t\"detail\": \"*\"\n//\t \t  \t}\n//\t \t  ]\n//\t\t  }\nfunc fromJSON(js []byte) (*chaosmonkey.AppConfig, error) {\n\tparsed := new(parsedJSON)\n\terr := json.Unmarshal(js, parsed)\n\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"json unmarshal failed\")\n\t}\n\n\tif parsed.Attributes == nil {\n\t\treturn nil, errors.New(\"'attributes' field missing\")\n\t}\n\n\tif parsed.Attributes.ChaosMonkey == nil {\n\t\treturn nil, errors.New(\"'attributes.chaosMonkey' field missing\")\n\t}\n\n\tcm := parsed.Attributes.ChaosMonkey\n\n\tif cm.Enabled == nil {\n\t\treturn nil, errors.New(\"'attributes.chaosMonkey.enabled' field missing\")\n\t}\n\n\t// Check if mean time between kills is missing.\n\t// If not enabled, it's ok if it's missing","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/Netflix/chaosmonkey/blob/eaa28fb761c0ebe8644d1333e5d164e9cc3071e9/spinnaker/fromjson.go#L80-L116","documentation":"fromJSON unmarshals the raw Spinnaker response into an internal parsedJSON structure. If json.Unmarshal fails, the error is wrapped as 'json unmarshal failed'. The response was readable HTTP 200 but its JSON shape/types do not match the expected struct.","triggerScenarios":"json.Unmarshal(js, parsed) returns an error: response is empty, HTML (e.g. an error page from a proxy), truncated JSON, or field types differing from parsedJSON expectations (e.g. a string where a number is expected).","commonSituations":"A reverse proxy or login page returning HTML with status 200; Spinnaker API version changes altering the response schema; interrupted responses producing truncated JSON; empty body from gate on odd conditions.","solutions":["Log/dump the raw response body (or its first bytes) to see what was actually received","Confirm the endpoint returns the expected Spinnaker application JSON (compare against a curl of the gate URL)","Check for proxies/auth layers returning HTML with 200 status","Verify the Spinnaker API version is compatible with this library's parsedJSON schema","Add a content-type check before unmarshaling"],"exampleFix":"// caller-side guard before trusting Get output\nbody, _ := ioutil.ReadAll(resp.Body)\nif !json.Valid(body) {\n    log.Printf(\"non-JSON response from gate: %.200s\", body)\n    return errors.New(\"gate returned invalid JSON\")\n}","handlingStrategy":"validation","validationCode":"body, err := ioutil.ReadAll(resp.Body)\nif err != nil { return err }\nif len(bytes.TrimSpace(body)) == 0 {\n    return errors.New(\"empty response body from gate\")\n}\nif !json.Valid(body) {\n    return fmt.Errorf(\"non-JSON response from gate: %.200s\", body)\n}","typeGuard":"func looksLikeGateJSON(body []byte) bool {\n    if !json.Valid(body) { return false }\n    var probe struct {\n        Attributes map[string]interface{} `json:\"attributes\"`\n    }\n    return json.Unmarshal(body, &probe) == nil && probe.Attributes != nil\n}","tryCatchPattern":"cfg, err := getter.Get(app)\nif err != nil && strings.Contains(err.Error(), \"json unmarshal failed\") {\n    log.Printf(\"gate returned malformed JSON for %s; check proxies/API version: %+v\", app, err)\n    return err\n}","preventionTips":["Pin and test against the Spinnaker API version this library expects","Reject HTML error pages early by checking Content-Type and json.Valid","Log a bounded snippet of the raw body when unmarshal fails","Watch for Spinnaker upgrades that change the applications response schema"],"tags":["go","json","spinnaker","unmarshal"],"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"}