Netflix/chaosmonkey · error
unexpected response code (%d) from %s
Error message
unexpected response code (%d) from %s
What it means
After a successful GET, Spinnaker.Get expects HTTP 200. Any other status code yields 'unexpected response code (%d) from %s'. This signals the gate responded but rejected or redirected the request rather than returning the app config payload.
Source
Thrown at spinnaker/config.go:43
// Get implements chaosmonkey.Getter.Get
func (s Spinnaker) Get(app string) (c *chaosmonkey.AppConfig, err error) {
// avoid expanding the response to avoid unneeded load
url := s.appURL(app) + "?expand=false"
resp, err := s.client.Get(url)
if err != nil {
return nil, errors.Wrapf(err, "http get failed at %s", url)
}
defer func() {
if cerr := resp.Body.Close(); cerr != nil && err == nil {
err = errors.Wrapf(err, "body close failed at %s", url)
}
}()
// should return a 200
if resp.StatusCode != http.StatusOK {
return nil, errors.Errorf("unexpected response code (%d) from %s", resp.StatusCode, url)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, errors.Wrapf(err, "body read failed at %s", url)
}
return fromJSON(body)
}
View on GitHub (pinned to eaa28fb761)
Solutions
- Check the reported status code: 404 means verify the app exists in Spinnaker; 401/403 means fix credentials/auth for the gate
- Confirm the app name used in appURL matches Spinnaker's application name exactly
- Inspect gate/proxy logs for 5xx causes (upstream Spinnaker health)
- Ensure the HTTP client follows redirects if a 3xx is returned
Example fix
// caller-side guard
resp, err := http.Get(gateURL + "/applications/myapp?expand=false")
if err != nil { return err }
if resp.StatusCode == http.StatusNotFound {
log.Println("app not found in spinnaker; skipping")
return nil
}
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("gate returned %d for %s", resp.StatusCode, gateURL)
} Defensive patterns
Strategy: type-guard
Validate before calling
resp, err := http.Get(gateURL + "/applications/" + app + "?expand=false")
if err != nil { return err }
switch {
case resp.StatusCode == http.StatusNotFound:
return fmt.Errorf("app %s does not exist in Spinnaker", app)
case resp.StatusCode == http.StatusUnauthorized || resp.StatusCode == http.StatusForbidden:
return errors.New("invalid or expired Spinnaker credentials")
case resp.StatusCode != http.StatusOK:
return fmt.Errorf("gate returned %d", resp.StatusCode)
} Type guard
func isNotFoundStatus(err error) bool {
m := regexp.MustCompile(`unexpected response code \((\d+)\)`).FindStringSubmatch(err.Error())
return m != nil && m[1] == "404"
} Try / catch
cfg, err := getter.Get(app)
if err != nil {
if isNotFoundStatus(err) {
log.Printf("skipping %s: not in Spinnaker", app)
return nil // treat as non-fatal
}
return err
} Prevention
- Keep Spinnaker credentials/tokens current and rotate before expiry
- Verify app names against Spinnaker's application list before processing
- Alert on 5xx rates from the gate and check proxy health
- Confirm expected app inventory nightly to catch deleted apps early
When it happens
Trigger: Spinnaker returns 404 (unknown app), 401/403 (missing/invalid auth), 5xx (gate internal error), or 3xx that the client did not follow for GET <appURL>?expand=false.
Common situations: Querying an app name that does not exist in Spinnaker; auth token/account credentials missing or expired; Spinnaker gate overloaded returning 502/503 from a proxy; app deleted after the monkey listed it.
Related errors
- http get failed at %s
- body read failed at %s
- http get failed at %s
- body close failed at %s
- POST to %s failed, (body '%s')
AI-assisted analysis of Netflix/chaosmonkey@eaa28fb761 (2026-09-03).
Data as JSON: /api/errors/8e273b4e016fce66.
Report an issue: GitHub.