chenhg5/cc-connect · error

cloud_web: send HTTP %d: %s

Error message

cloud_web: send HTTP %d: %s

What it means

The gateway transport POSTed an outbound message to the cloud-web server's send endpoint and the server replied with HTTP status >= 300. The error includes the status code and up to 1MB of the response body for diagnosis. This means the message was not accepted by the server.

Source

Thrown at platform/cloud-web/gateway.go:285

	body, err := json.Marshal(msg)
	if err != nil {
		return err
	}
	url := joinURL(t.baseURL, t.sendPath)
	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, _ := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
	if resp.StatusCode >= 300 {
		return fmt.Errorf("cloud_web: send HTTP %d: %s", resp.StatusCode, string(raw))
	}
	var ack wirePreviewAck
	if json.Unmarshal(raw, &ack) == nil && ack.Type == "preview_ack" && ack.RefID != "" {
		t.previewMu.Lock()
		ch, ok := t.previewRequests[ack.RefID]
		if ok {
			delete(t.previewRequests, ack.RefID)
		}
		t.previewMu.Unlock()
		if ok {
			ch <- ack.PreviewHandle
		}
	}
	return nil
}

func (t *gatewayTransport) waitPreviewAck(refID string, timeout time.Duration) (string, error) {
	ch := make(chan string, 1)

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Inspect the status/body in the error: 401 -> fix the token; 404 -> fix base_url/send_path; 5xx -> check server logs.
  2. Verify the token in config.toml matches the cloud-web server's shared secret.
  3. Confirm base_url + send_path form the correct full endpoint URL (curl -H "Authorization: Bearer $TOKEN" the endpoint).
  4. Retry after fixing; transient 502/504 usually means the server or its proxy was briefly unavailable.

Example fix

// config.toml — before
base_url = "https://cloud.example.com"  # server mounts API under /api -> 404

// after
base_url = "https://cloud.example.com/api"
Defensive patterns

Strategy: try-catch

Validate before calling

// verify send endpoint + auth before going live
req, _ := http.NewRequest("POST", sendURL, bytes.NewReader([]byte("{}")))
req.Header.Set("Authorization", "Bearer "+token)
resp, err := http.DefaultClient.Do(req)
if err != nil {
    return err
}
resp.Body.Close()
if resp.StatusCode >= 300 {
    return fmt.Errorf("send endpoint returned %d; fix base_url/send_path/token", resp.StatusCode)
}

Try / catch

if err := platform.Send(ctx, msg); err != nil {
    var retriable bool
    if strings.Contains(err.Error(), "send HTTP 5") || strings.Contains(err.Error(), "send HTTP 429") {
        retriable = true
    }
    slog.Error("cloud-web send failed", "error", err, "retriable", retriable)
    if retriable {
        time.Sleep(time.Second)
        return platform.Send(ctx, msg)
    }
    return err
}

Prevention

When it happens

Trigger: Send() receives a response with status 3xx/4xx/5xx: 401 on token mismatch, 404 on wrong send_path or base_url path prefix, 413 on oversized payloads, 500/502 on server or proxy failure.

Common situations: Rotated token not updated in cc-connect config; base_url missing a path prefix (e.g. behind /api) so send_path resolves to 404; reverse proxy timing out with 502/504; server bug returning 500.

Related errors


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