{"record":{"id":"0ce634417f66249d","repo":"henrygd/beszel","slug":"s-returned-status-d","errorCode":null,"errorMessage":"%s returned status %d","messagePattern":"(.+?) returned status (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cmd/hub/hub.go","lineNumber":99,"sourceCode":"\thealthCmd.Flags().StringVar(&baseURL, \"url\", \"\", \"base URL\")\n\thealthCmd.MarkFlagRequired(\"url\")\n\treturn healthCmd\n}\n\n// checkHealth checks the health of the hub.\nfunc checkHealth(baseURL string) error {\n\tclient := &http.Client{\n\t\tTimeout: time.Second * 3,\n\t}\n\thealthURL := baseURL + \"/api/health\"\n\tresp, err := client.Get(healthURL)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != 200 {\n\t\treturn fmt.Errorf(\"%s returned status %d\", healthURL, resp.StatusCode)\n\t}\n\treturn nil\n}\n","sourceCodeStart":81,"sourceCodeEnd":103,"githubUrl":"https://github.com/henrygd/beszel/blob/b38fb7dafa60812cc22e6a84ce313e94f1ce0a32/internal/cmd/hub/hub.go#L81-L103","documentation":"checkHealth polls the hub's health endpoint and treats the service as healthy only when the HTTP status is exactly 200. Any other status (404, 403, 500, 502, 503) is reported with this error including the URL and received status, so callers can fail startup or keep wait-looping.","triggerScenarios":"GET healthURL returns a non-200 response: the hub is still starting, the URL/port points at the wrong service, a reverse proxy intercepts the path (404/502), or auth middleware blocks the health route.","commonSituations":"Docker healthcheck racing container startup (503 during boot); health path misconfigured behind nginx/Traefik; port mapped to another container; hub crashed and the platform returns 502/503.","solutions":["Check hub logs for startup errors; if still booting, retry — transient during rollout.","Verify healthURL scheme/host/port/path matches the hub's actual health route; curl it from inside the network to compare.","If a proxy returns 404, exempt the health endpoint from auth/routing rewrites.","Confirm the port mapping points at the hub process; fix compose/port config and restart."],"exampleFix":"// before\nif resp.StatusCode != 200 {\n\treturn fmt.Errorf(\"%s returned status %d\", healthURL, resp.StatusCode)\n}\n// after\nif resp.StatusCode != http.StatusOK {\n\treturn fmt.Errorf(\"%s returned status %d (hub may still be starting; check hub logs)\", healthURL, resp.StatusCode)\n} // pair with a retry/backoff loop in the caller","handlingStrategy":"retry","validationCode":"// probe the endpoint yourself before declaring failure\nresp, err := http.Get(healthURL)\nif err != nil || resp.StatusCode != http.StatusOK {\n\tlog.Printf(\"hub not ready yet (%v)\", err)\n}","typeGuard":null,"tryCatchPattern":"var err error\nfor i := 0; i < 30; i++ {\n\tif err = checkHealth(healthURL); err == nil {\n\t\tbreak\n\t}\n\ttime.Sleep(2 * time.Second) // hub may still be starting\n}\nif err != nil {\n\tlog.Fatalf(\"health check failed: %v\", err)\n}","preventionTips":["Configure healthchecks with start_period/retries to tolerate boot time.","Verify health URL path and port, especially behind reverse proxies.","Exempt the health endpoint from auth middleware.","Curl the endpoint from inside the network when debugging."],"tags":["go","http","healthcheck","status-code"],"backgroundTag":"http-non-200-status","analyzedSha":"b38fb7dafa60812cc22e6a84ce313e94f1ce0a32","analyzedAt":"2026-08-31T15:10:10.149Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}