chenhg5/cc-connect · error

do request: %w

Error message

do request: %w

What it means

This error wraps a network-level failure from httpClient.Do when POSTing the createAndDeliver request (platform/dingtalk/card.go:131, createAICard). It means the request never got an HTTP response: DNS failure, connection refused/reset, TLS error, or the 30-second context timeout (reqCtx) expired. No DingTalk API call happened, so no rate limit or auth logic applies.

Source

Thrown at platform/dingtalk/card.go:131

	reqCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
	defer cancel()

	req, err := http.NewRequestWithContext(reqCtx, http.MethodPost,
		"https://api.dingtalk.com/v1.0/card/instances/createAndDeliver",
		bytes.NewReader(bodyBytes))
	if err != nil {
		return nil, fmt.Errorf("create request: %w", err)
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("x-acs-dingtalk-access-token", token)

	slog.Debug("dingtalk: creating AI card", "outTrackId", outTrackId, "isGroup", isGroup)

	resp, err := p.httpClient.Do(req)
	if err != nil {
		return nil, fmt.Errorf("do request: %w", err)
	}
	defer resp.Body.Close()

	respBody, _ := io.ReadAll(resp.Body)

	slog.Debug("dingtalk: createAndDeliver response",
		"status", resp.StatusCode,
		"body", string(respBody))

	if resp.StatusCode != http.StatusOK {
		slog.Error("dingtalk: create AI card failed",
			"status", resp.StatusCode,
			"body", string(respBody))
		// Check if we should trigger degrade
		if resp.StatusCode == 403 || resp.StatusCode == 429 || resp.StatusCode >= 500 {
			p.activateCardDegrade(fmt.Sprintf("card.create:%d", resp.StatusCode))
		}
		return nil, fmt.Errorf("create AI card: status=%d, body=%s", resp.StatusCode, string(respBody))

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Check host egress: curl -v https://api.dingtalk.com/v1.0/card/instances/createAndDeliver from the same machine
  2. Inspect the wrapped error: *url.Error with "context deadline exceeded" means the 30s timeout fired; "connection refused"/"no such host" means network/DNS
  3. Configure the platform's httpClient proxy if behind a corporate proxy (http.Transport Proxy setting)
  4. Retry the card creation — flush/Finalize paths tolerate transient stream failures, and card degrade mode activates on repeated failures
  5. Check logs for activateCardDegrade; if degraded to plain text messages, fix connectivity first
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight connectivity check
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
req, _ := http.NewRequestWithContext(ctx, "GET", "https://api.dingtalk.com", nil)
if _, err := http.DefaultClient.Do(req); err != nil {
	log.Printf("dingtalk unreachable: %v", err)
}
cancel()

Try / catch

card, err := p.CreateStreamingCard(ctx, msg)
if err != nil {
	var ne *net.OpError
	var te *url.Error
	if errors.As(err, &ne) || (errors.As(err, &te) && te.Timeout()) {
		// transient network issue: retry with backoff or fall back to plain text
	}
}

Prevention

When it happens

Trigger: httpClient.Do returns error during CreateStreamingCard: DNS resolution failure for api.dingtalk.com, TCP connect refused/blocked, TLS handshake failure, or the 30s reqCtx deadline exceeded before a response.

Common situations: No outbound internet access or firewalled egress on the host; api.dingtalk.com blocked by corporate proxy/firewall; transient network flaps; slow network pushing the request past the 30s timeout; IPv6 misrouting.

Related errors


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