chenhg5/cc-connect · warning

cloud_web: events HTTP %d: %s

Error message

cloud_web: events HTTP %d: %s

What it means

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.

Source

Thrown at platform/cloud-web/poll.go:162

	}
	url := joinURL(t.baseURL, t.eventsPath)
	req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(body))
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "application/json")
	authHTTP(req, t.token)
	resp, err := t.client.Do(req)
	if err != nil {
		return err
	}
	defer func() { _ = resp.Body.Close() }()
	raw, err := io.ReadAll(io.LimitReader(resp.Body, 4<<20))
	if err != nil {
		return err
	}
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("cloud_web: events HTTP %d: %s", resp.StatusCode, string(raw))
	}
	return t.dispatchBatch(raw)
}

func (t *pollTransport) dispatchBatch(raw []byte) error {
	if t.dispatchBatchPayload(raw) {
		return nil
	}
	t.dispatchOne(raw)
	return nil
}

func (t *pollTransport) dispatchBatchPayload(raw []byte) bool {
	var base wireMsg
	if err := json.Unmarshal(raw, &base); err == nil {
		switch base.Type {
		case "message", "card_action", "message_recall", "ping":
			t.dispatchOne(raw)

View on GitHub (pinned to 4000b2338a)

Solutions

  1. 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.
  2. Set events_path in config.toml to the server's actual events route (default /events).
  3. Configure the proxy (nginx proxy_read_timeout / LB idle timeout) to exceed the poll timeout.
  4. Watch server health; persistent 5xx means the cloud-web service needs attention.

Example fix

// nginx — before
proxy_read_timeout 10s;   # kills 30s long polls with 504

// after
proxy_read_timeout 75s;
Defensive patterns

Strategy: retry

Validate before calling

// verify events endpoint health before/while polling
req, _ := http.NewRequest("POST", baseURL+"/events", strings.NewReader("{}"))
req.Header.Set("Authorization", "Bearer "+token)
resp, err := http.DefaultClient.Do(req)
if err == nil {
    resp.Body.Close()
    if resp.StatusCode == 401 || resp.StatusCode == 404 {
        return fmt.Errorf("events endpoint misconfigured (status %d); fix token/events_path", resp.StatusCode)
    }
}

Try / catch

// pollLoop already retries every 1s; alert on persistence instead of swallowing
if strings.Contains(err.Error(), "events HTTP 401") {
    slog.Error("poll auth failing — stop retrying and fix the token", "error", err)
    cancelPolling()
} else {
    slog.Warn("transient poll error; backing off", "error", err)
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/4e28f9ab09db71b0. Report an issue: GitHub.