chenhg5/cc-connect · error

dingtalk: proactive send request: %w

Error message

dingtalk: proactive send request: %w

What it means

The HTTP transport layer failed while POSTing the proactive message to the DingTalk API. This wraps the client-side network error (DNS failure, connection refused, TLS error, timeout) returned by p.httpClient.Do(req), before any HTTP status is received.

Source

Thrown at platform/dingtalk/dingtalk.go:1692

	} else {
		return fmt.Errorf("dingtalk: proactive send requires conversationId (group) or senderStaffId (direct)")
	}

	body, err := json.Marshal(requestBody)
	if err != nil {
		return fmt.Errorf("dingtalk: marshal proactive message: %w", err)
	}

	req, err := http.NewRequestWithContext(ctx, http.MethodPost, apiURL, bytes.NewReader(body))
	if err != nil {
		return fmt.Errorf("dingtalk: create proactive request: %w", err)
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("x-acs-dingtalk-access-token", token)

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

	respBody, _ := io.ReadAll(resp.Body)
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("dingtalk: proactive send failed: status=%d, body=%s", resp.StatusCode, string(respBody))
	}

	slog.Debug("dingtalk: proactive message sent", "api", apiURL, "status", resp.StatusCode)
	return nil
}

var atUserIDRegexp = regexp.MustCompile(`@(\d{4,})`)

// extractAtUserIds extracts @userId patterns from content for DingTalk's atUserIds field.
// Matches @ followed by numeric DingTalk user IDs (e.g. @194252073827812352).
func extractAtUserIds(content string) []string {
	matches := atUserIDRegexp.FindAllStringSubmatch(content, -1)

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Check basic connectivity to the DingTalk API host (curl https://api.dingtalk.com) from the host running cc-connect.
  2. If a proxy is configured in the dingtalk platform options, verify the proxy URL, credentials, and that the proxy is reachable.
  3. Inspect the wrapped error (%w): context deadline exceeded → increase the HTTP client timeout; connection refused/proxy → fix network or proxy settings.
  4. Add retry with backoff for transient network failures on this idempotent send path.

Example fix

// before
err := p.Send(ctx, rc, msg) // fires once, no timeout budget
// after
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
err := p.Send(ctx, rc, msg)
Defensive patterns

Strategy: retry

Validate before calling

conn, err := net.DialTimeout("tcp", "api.dingtalk.com:443", 3*time.Second)
if err != nil {
    slog.Warn("dingtalk unreachable", "err", err)
} else {
    conn.Close()
}

Try / catch

var nerr net.Error
if errors.As(err, &nerr) && nerr.Timeout() {
    // retry with backoff
}
if err := p.Send(ctx, rc, msg); err != nil {
    slog.Warn("proactive send transport error", "err", err)
}

Prevention

When it happens

Trigger: p.httpClient.Do(req) returns a non-nil error for the proactive-send POST — network unreachable, DNS resolution failure, proxy failure, or context deadline exceeded mid-request.

Common situations: No internet access or blocked access to api.dingtalk.com (firewall/corporate proxy); proxy misconfiguration in the platform options; request timeout set too low; DingTalk service outage.

Related errors


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