{"record":{"id":"4e28f9ab09db71b0","repo":"chenhg5/cc-connect","slug":"cloud-web-events-http-d-s","errorCode":null,"errorMessage":"cloud_web: events HTTP %d: %s","messagePattern":"cloud_web: events HTTP (.+?): (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"platform/cloud-web/poll.go","lineNumber":162,"sourceCode":"\t}\n\turl := joinURL(t.baseURL, t.eventsPath)\n\treq, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(body))\n\tif err != nil {\n\t\treturn err\n\t}\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\tauthHTTP(req, t.token)\n\tresp, err := t.client.Do(req)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer func() { _ = resp.Body.Close() }()\n\traw, err := io.ReadAll(io.LimitReader(resp.Body, 4<<20))\n\tif err != nil {\n\t\treturn err\n\t}\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn fmt.Errorf(\"cloud_web: events HTTP %d: %s\", resp.StatusCode, string(raw))\n\t}\n\treturn t.dispatchBatch(raw)\n}\n\nfunc (t *pollTransport) dispatchBatch(raw []byte) error {\n\tif t.dispatchBatchPayload(raw) {\n\t\treturn nil\n\t}\n\tt.dispatchOne(raw)\n\treturn nil\n}\n\nfunc (t *pollTransport) dispatchBatchPayload(raw []byte) bool {\n\tvar base wireMsg\n\tif err := json.Unmarshal(raw, &base); err == nil {\n\t\tswitch base.Type {\n\t\tcase \"message\", \"card_action\", \"message_recall\", \"ping\":\n\t\t\tt.dispatchOne(raw)","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/cloud-web/poll.go#L144-L180","documentation":"A long-poll request to the cloud-web events endpoint returned a non-200 status. pollLoop treats this as a transient poll error: it logs at debug level, sleeps one second, and retries — so this error surfaces in logs rather than to the caller. It indicates the server rejected the poll (auth, routing, or server health), not a malformed event batch.","triggerScenarios":"pollOnce receives status != 200 on POST {base_url}/{events_path}: 401 on token mismatch, 404 on wrong events path, 408/504 from an intermediary cutting off long-poll waits, 5xx on server errors.","commonSituations":"Reverse proxy with a short read timeout killing long polls with 504; token rotated server-side causing endless 401 retries; events_path customized in config but not matching the server route; server restarts.","solutions":["Check logs for the repeated status: 401 -> fix token; 404 -> fix events_path/base_url; 504 -> raise proxy read timeout above the poll timeout_ms.","Set events_path in config.toml to the server's actual events route (default /events).","Configure the proxy (nginx proxy_read_timeout / LB idle timeout) to exceed the poll timeout.","Watch server health; persistent 5xx means the cloud-web service needs attention."],"exampleFix":"// nginx — before\nproxy_read_timeout 10s;   # kills 30s long polls with 504\n\n// after\nproxy_read_timeout 75s;","handlingStrategy":"retry","validationCode":"// verify events endpoint health before/while polling\nreq, _ := http.NewRequest(\"POST\", baseURL+\"/events\", strings.NewReader(\"{}\"))\nreq.Header.Set(\"Authorization\", \"Bearer \"+token)\nresp, err := http.DefaultClient.Do(req)\nif err == nil {\n    resp.Body.Close()\n    if resp.StatusCode == 401 || resp.StatusCode == 404 {\n        return fmt.Errorf(\"events endpoint misconfigured (status %d); fix token/events_path\", resp.StatusCode)\n    }\n}","typeGuard":null,"tryCatchPattern":"// pollLoop already retries every 1s; alert on persistence instead of swallowing\nif strings.Contains(err.Error(), \"events HTTP 401\") {\n    slog.Error(\"poll auth failing — stop retrying and fix the token\", \"error\", err)\n    cancelPolling()\n} else {\n    slog.Warn(\"transient poll error; backing off\", \"error\", err)\n}","preventionTips":["Set proxy/LB idle timeouts above the poll timeout_ms (e.g. 75s for 30s polls)","Alert on repeated identical events HTTP statuses rather than relying on debug logs","Keep events_path aligned with the server route","Track token rotation in both server and client configs"],"tags":["http","long-polling","retry","cloud-web"],"backgroundTag":"http-non-200-response","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}