{"record":{"id":"4a060e9022310a65","repo":"Netflix/chaosmonkey","slug":"unexpected-status-code-d-body-s","errorCode":null,"errorMessage":"unexpected status code: %d. body: %s","messagePattern":"unexpected status code: (.+?)\\. body: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"spinnaker/terminator.go","lineNumber":192,"sourceCode":"\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 {\n\t\treturn \"\", nil\n\t}\n\n\t// If the instance id is the same, there is no alternate\n\tif ins.ID() == otherID {","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/Netflix/chaosmonkey/blob/eaa28fb761c0ebe8644d1333e5d164e9cc3071e9/spinnaker/terminator.go#L174-L210","documentation":"OtherID() fetches instance details from Spinnaker to determine an alternate instance ID. When the HTTP status is not 200 and the decoded response contains no Error field, this error includes the status code and raw body.","triggerScenarios":"Calling OtherID (from Execute) when the instance-details request returns e.g. 404 (instance gone), 401/403 (auth), or 5xx and the JSON body has an empty Error field.","commonSituations":"Terminating an instance that was already terminated (404), stale credentials, Spinnaker outage with a non-JSON error page.","solutions":["Check the body: 404 usually means the instance no longer exists — handle idempotently","Refresh Spinnaker credentials for 401/403","Verify the instance ID/account passed to OtherID","Retry on 5xx; investigate Spinnaker server logs"],"exampleFix":"// before\nreturn \"\", fmt.Errorf(\"unexpected status code: %d. body: %s\", resp.StatusCode, body)\n// after\nif resp.StatusCode == http.StatusNotFound {\n    return \"\", nil // instance already gone; treat as terminated\n}\nreturn \"\", fmt.Errorf(\"unexpected status code: %d. body: %s\", resp.StatusCode, body)","handlingStrategy":"try-catch","validationCode":"// verify the instance exists before calling OtherID/Execute\n// list instances for the account and confirm the ID is present","typeGuard":null,"tryCatchPattern":"otherID, err := terminator.Execute(...)\nif err != nil {\n    if strings.Contains(err.Error(), \"404\") {\n        log.Printf(\"instance already gone; treating as terminated\")\n    } else {\n        return err\n    }\n}","preventionTips":["Treat 404 as idempotent success for termination flows","Refresh credentials on 401/403","Validate instance IDs against the cloud provider","Retry 5xx with backoff"],"tags":["http","spinnaker","instance-lookup"],"backgroundTag":"unexpected-http-status","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"}