chenhg5/cc-connect · error

dingtalk: create file request: %w

Error message

dingtalk: create file request: %w

What it means

This error wraps a failure from http.NewRequestWithContext while building the POST to DingTalk's oToMessages batchSend API when sending a file. NewRequestWithContext only fails on an invalid HTTP method or an unparseable URL, so in practice this almost never fires with the hardcoded constant URL. It is a defensive guard; if you see it, the request could not even be constructed.

Source

Thrown at platform/dingtalk/dingtalk.go:1149

		"fileType": ext,
	})
	requestBody := map[string]any{
		"robotCode": p.robotCode,
		"userIds":   []string{rc.senderStaffId},
		"msgKey":    "sampleFile",
		"msgParam":  string(msgParamBytes),
	}

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

	req, err := http.NewRequestWithContext(ctx, http.MethodPost,
		"https://api.dingtalk.com/v1.0/robot/oToMessages/batchSend",
		bytes.NewReader(body))
	if err != nil {
		return fmt.Errorf("dingtalk: create file 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: send file request: %w", err)
	}
	defer func() { _ = resp.Body.Close() }()

	respBody, _ := io.ReadAll(resp.Body)
	slog.Debug("dingtalk: oToMessages file response", "status", resp.StatusCode, "body", string(respBody))

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

	slog.Info("dingtalk: file message sent", "media_id", mediaID, "name", name, "user", rc.senderStaffId)

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Check the wrapped error (%w) for the real cause — it names the URL parse or method problem
  2. If the endpoint URL was made configurable, validate it with url.Parse before passing it in
  3. Retry; transient resource exhaustion resolves itself
  4. Report a bug if it reproduces with unmodified code

Example fix

// before (dynamic URL)
req, err := http.NewRequestWithContext(ctx, http.MethodPost, cfg.BaseURL+"/v1.0/robot/oToMessages/batchSend", bytes.NewReader(body))
// after (validate first)
u, err := url.Parse(cfg.BaseURL)
if err != nil { return fmt.Errorf("dingtalk: invalid base url: %w", err) }
req, err := http.NewRequestWithContext(ctx, http.MethodPost, u.JoinPath("v1.0/robot/oToMessages/batchSend").String(), bytes.NewReader(body))
Defensive patterns

Strategy: try-catch

Validate before calling

if u, err := url.Parse("https://api.dingtalk.com/v1.0/robot/oToMessages/batchSend"); err != nil { /* fail fast */ }

Try / catch

if err := p.SendFile(ctx, rc, data, name); err != nil { if strings.Contains(err.Error(), "create file request") { log.Fatalf("request construction failed: %v", err) } }

Prevention

When it happens

Trigger: Calling SendFile with a reply context that yields a valid token, but http.NewRequestWithContext failing to construct the request for https://api.dingtalk.com/v1.0/robot/oToMessages/batchSend (invalid URL/method — practically impossible with the hardcoded constants, e.g. memory exhaustion or a malformed internal URL if modified).

Common situations: Only seen in exotic conditions: out-of-memory, or a developer modifying the code to build the URL dynamically (e.g. from config with a bad custom endpoint) producing an unparseable URL.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


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