{"record":{"id":"c9e21a9be725f1a7","repo":"nsqio/nsq","slug":"got-response-s-q","errorCode":null,"errorMessage":"got response %s %q","messagePattern":"got response (.+?) %q","errorType":"http","errorClass":null,"httpStatus":502,"severity":"error","filePath":"internal/http_api/api_request.go","lineNumber":81,"sourceCode":"\t}\n\n\tbody, err := io.ReadAll(resp.Body)\n\tcloseErr := resp.Body.Close()\n\tif err != nil {\n\t\treturn err\n\t}\n\tif closeErr != nil {\n\t\treturn closeErr\n\t}\n\tif resp.StatusCode != 200 {\n\t\tif resp.StatusCode == 403 && !strings.HasPrefix(endpoint, \"https\") {\n\t\t\tendpoint, err = httpsEndpoint(endpoint, body)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tgoto retry\n\t\t}\n\t\treturn fmt.Errorf(\"got response %s %q\", resp.Status, body)\n\t}\n\terr = json.Unmarshal(body, &v)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n// PostV1 is a helper function to perform a V1 HTTP request\n// and parse our NSQ daemon's expected response format, with deadlines.\nfunc (c *Client) POSTV1(endpoint string, data url.Values, v interface{}) error {\nretry:\n\tvar reqBody io.Reader\n\tif data != nil {\n\t\tjs, err := json.Marshal(data)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to marshal POST data to endpoint: %v\", endpoint)","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/nsqio/nsq/blob/85cf10c09c6c3c86160d6f0eb156f62d0efc1648/internal/http_api/api_request.go#L63-L99","documentation":"internal/http_api's Client.GETV1 (api_request.go) is the helper nsqadmin, nsqlookupd and the apps use to GET an nsqd/nsqlookupd HTTP API endpoint (e.g. /info, /stats, /lookup) with timeouts and negotiate-v1. On any response whose status is not exactly 200 it returns 'got response %s %q' with the HTTP status line and the (possibly empty) response body; one special case is handled internally: a 403 over http triggers an https retry via the https_port advertised by the daemon. Non-200 therefore means the daemon answered but rejected the request.","triggerScenarios":"Querying a wrong port (a non-NSQ HTTP server returning 404 with an HTML body), an nsqd endpoint that errors (500 on /stats under corruption), 401/403 when TLS-client-auth or auth is required and the client sent no credentials, or hitting an endpoint that moved. Used pervasively by nsqadmin pages and by nsq_to_nsq/nssql-style tools that create topics via /topic/create.","commonSituations":"nsqadmin configured with --nsqd-http-address pointing at the wrong port (e.g. the TCP 4150 instead of HTTP 4151); auth-enabled nsqd while nsqadmin lacks --http-client-auth-* / notification credentials; reverse proxy in front of nsqd returning 403 or 502 HTML that swallows the real status; version skew where an endpoint was removed.","solutions":["Replay the exact URL with curl from the nsqadmin host: 'curl -i http://nsqd:4151/info' — it must return 200 with JSON.","Fix the address/port in --lookupd-http-address / --nsqd-http-address (HTTP port, default 4151 for nsqd, 4161 for lookupd).","If nsqd runs TLS-only or requires client certs, configure the http-client TLS options (and note 403+http auto-retries https only when the daemon advertises https_port).","When auth is enabled, provision nsqadmin's allowed auth secret / client cert so requests are authorized."],"exampleFix":"# before\nnsqadmin --nsqd-http-address=10.0.0.1:4150\n# got response \"404 Not Found\" \"<html>...\"  (4150 is the TCP port)\n\n# after\nnsqadmin --nsqd-http-address=10.0.0.1:4151\ncurl -i http://10.0.0.1:4151/info   # 200 OK application/json","handlingStrategy":"try-catch","validationCode":"// before driving the UI/tools, verify each daemon answers 200 on its HTTP API\nfunc nsqdAPIAlive(base string) error {\n    c := &http.Client{Timeout: 2 * time.Second}\n    resp, err := c.Get(base + \"/info\")\n    if err != nil {\n        return err\n    }\n    defer resp.Body.Close()\n    if resp.StatusCode != http.StatusOK {\n        return fmt.Errorf(\"%s/info answered %d — fix address/auth before proceeding\", base, resp.StatusCode)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"// around http_api GETV1 callers: classify the response error instead of string-matching blindly\nif err := client.GETV1(endpoint, &v); err != nil {\n    if strings.Contains(err.Error(), \"got response\") {\n        // daemon reachable but refused: log status+body, alert on 4xx config errors,\n        // retry later on 5xx after the daemon recovers\n        return classifyAndRetry(err)\n    }\n    return err // transport-level failure (timeout, refused) — different remediation\n}","preventionTips":["Smoke-test /info on every configured address before starting nsqadmin.","Point admin tooling at the HTTP ports (nsqd 4151, lookupd 4161), never the TCP ports.","When auth/TLS client certs are required on nsqd, configure the http-client TLS flags on the caller side too.","Keep proxies from rewriting nsqd status codes."],"tags":["http","api-client","nsqadmin","status-code","configuration"],"backgroundTag":null,"analyzedSha":"85cf10c09c6c3c86160d6f0eb156f62d0efc1648","analyzedAt":"2026-08-16T00:53:05.009Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}