m1k1o/neko · error
unexpected status code: %d, body: %s
Error message
unexpected status code: %d, body: %s
What it means
This error is the fallback branch of session.req: the backend returned a non-success status code and the body could NOT be parsed as a JSON object with a 'message' field, so the raw status code and (trimmed) body are embedded in the error. It indicates an unexpected backend response format — often an HTML error page, empty body, or plain text from a proxy/load balancer rather than the application backend itself.
Source
Thrown at server/internal/http/legacy/session.go:107
res, err := s.client.Do(req)
if err != nil {
return nil, nil, err
}
if res.StatusCode < 200 || res.StatusCode >= 300 {
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
// try to unmarsal as json error message
var apiErr struct {
Message string `json:"message"`
}
if err := json.Unmarshal(body, &apiErr); err == nil {
return nil, nil, fmt.Errorf("%w: %s", ErrBackendRespone, apiErr.Message)
}
// return raw body if failed to unmarshal
return nil, nil, fmt.Errorf("unexpected status code: %d, body: %s", res.StatusCode, strings.TrimSpace(string(body)))
}
return res.Body, res.Header, nil
}
func (s *session) apiReq(method, path string, request, response any) error {
reqBody, err := json.Marshal(request)
if err != nil {
return err
}
headers := http.Header{
"Content-Type": []string{"application/json"},
}
resBody, _, err := s.req(method, path, headers, bytes.NewReader(reqBody))
if err != nil {
return errView on GitHub (pinned to b0f01cedea)
Solutions
- Check the status code and body text embedded in the error to see which infrastructure layer answered.
- Verify the backend process is running and reachable at the configured URL (curl the endpoint directly).
- Inspect reverse proxy / load balancer logs between the proxy and backend.
- Fix infrastructure issues or make the backend return structured JSON errors on failure paths.
Example fix
// before
if err := s.apiReq("GET", "/api/stats", nil, &newStats); err != nil {
return err
}
// after
if err := s.apiReq("GET", "/api/stats", nil, &newStats); err != nil {
if strings.Contains(err.Error(), "unexpected status code: 50") {
return fmt.Errorf("backend unavailable, retry later: %w", err)
}
return err
} Defensive patterns
Strategy: retry
Validate before calling
resp, err := http.Get(backendURL + "/api/stats")
if err != nil {
return fmt.Errorf("backend unreachable: %w", err)
}
ct := resp.Header.Get("Content-Type")
if !strings.Contains(ct, "application/json") {
return fmt.Errorf("backend answered non-JSON (%s); infrastructure issue likely", ct)
} Type guard
func isNonJSONStatusError(err error) bool {
return strings.Contains(err.Error(), "unexpected status code:")
} Try / catch
err := s.apiReq(method, path, req, &out)
if strings.Contains(err.Error(), "unexpected status code: 50") {
// transient infra failure: retry with backoff
time.Sleep(2 * time.Second)
err = s.apiReq(method, path, req, &out)
} Prevention
- Health-check the backend (JSON endpoint) before starting API traffic.
- Inspect reverse proxy/LB logs when non-JSON bodies appear.
- Ensure the backend always returns JSON on error paths.
- Distinguish 5xx (retry) from 4xx (fix request/auth) in handling.
When it happens
Trigger: apiReq hits a non-2xx response whose body is not JSON — e.g. an nginx 502 Bad Gateway HTML page, an empty 500 body, a Cloudflare block page, or a plain-text panic output.
Common situations: Backend process down behind a reverse proxy (502/504); TLS or routing misconfiguration landing on the wrong service; WAF/CDN intercepting requests; backend crash producing non-JSON output.
Related errors
AI-assisted analysis of m1k1o/neko@b0f01cedea (2026-09-01).
Data as JSON: /api/errors/0ab3638246994ec6.
Report an issue: GitHub.