chenhg5/cc-connect · error
build request: %w
Error message
build request: %w
What it means
resourceSingleGet builds the HTTP GET request for the Feishu resource endpoint with http.NewRequestWithContext; if request construction fails (malformed URL, invalid method/context), the error is wrapped as "build request". This path is used for small files and as a fallback when the chunked size probe fails.
Source
Thrown at platform/feishu/resource_download.go:257
return n, true
}
// resourceURL builds the Feishu message-resource endpoint URL. Feishu
// serves this on the same base URL as the rest of the API; we use the
// configured domain so Lark international deployments also work.
func (p *Platform) resourceURL(messageID, fileKey, resType string) string {
return fmt.Sprintf("%s/open-apis/im/v1/messages/%s/resources/%s?type=%s",
strings.TrimRight(p.domain, "/"), messageID, fileKey, resType)
}
// resourceSingleGet downloads the entire resource with one plain GET. Used
// for small files and as a fallback when the size probe fails. We honour
// resourceMaxBytes via Content-Length + body cap so a misbehaving server
// can't blow up memory.
func (p *Platform) resourceSingleGet(ctx context.Context, token, messageID, fileKey, resType string) ([]byte, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, p.resourceURL(messageID, fileKey, resType), nil)
if err != nil {
return nil, fmt.Errorf("build request: %w", err)
}
req.Header.Set("Authorization", "Bearer "+token)
resp, err := p.resourceDownloadHTTP.Do(req)
if err != nil {
return nil, fmt.Errorf("resource request: %w", err)
}
defer func() { _ = resp.Body.Close() }()
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
body, _ := io.ReadAll(io.LimitReader(resp.Body, 4*1024))
return nil, fmt.Errorf("resource API status=%d body=%q", resp.StatusCode, strings.TrimSpace(string(body)))
}
if cl := resp.ContentLength; cl > p.resourceMaxBytes {
return nil, fmt.Errorf("resource too large: Content-Length=%d exceeds cap %d", cl, p.resourceMaxBytes)
}
View on GitHub (pinned to 4000b2338a)
Solutions
- Inspect the wrapped cause (%w) — url.Parse errors name the exact malformed part of the URL
- Log and validate messageID and fileKey before calling the download; ensure they come from a properly parsed Feishu message
- Check p.resourceURL / base URL configuration for typos or missing scheme
- Reject empty fileKey/messageID early instead of letting them produce an invalid URL
Example fix
// before
data, err := p.resourceSingleGet(ctx, token, msgID, fileKey, resType)
// after: validate inputs first
if msgID == "" || fileKey == "" {
return nil, fmt.Errorf("feishu: invalid message_id=%q file_key=%q", msgID, fileKey)
}
data, err := p.resourceSingleGet(ctx, token, msgID, fileKey, resType) Defensive patterns
Strategy: validation
Validate before calling
func validResourceInputs(msgID, fileKey string) bool {
return msgID != "" && fileKey != "" && !strings.ContainsFunc(fileKey, func(r rune) bool { return r < 0x21 || r == '%' })
}
// call before download
if !validResourceInputs(msgID, fileKey) { return fmt.Errorf("invalid resource identifiers") } Try / catch
data, err := p.resourceSingleGet(ctx, token, msgID, fileKey, resType)
if err != nil {
if strings.Contains(err.Error(), "build request") {
return nil, fmt.Errorf("invalid resource URL inputs: %w", err)
}
return nil, err
} Prevention
- Validate message_id and file_key as non-empty, URL-safe strings before download
- Parse file_key out of message metadata with strict checks
- Keep the Feishu base URL configuration correct and scheme-complete
When it happens
Trigger: p.resourceURL(messageID, fileKey, resType) returns a URL that http.NewRequestWithContext cannot parse — empty or malformed message_id/file_key, characters needing escaping (control chars, spaces) embedded in the file key, or a misconfigured base URL.
Common situations: fileKey extracted from a message contains unexpected characters or is empty because the message metadata was parsed incorrectly; base URL misconfigured in a self-hosted/proxy setup; resType misspelled by a caller constructing the URL path.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
- build first-chunk request: %w
- build range request: %w
- weixin: %s: new request: %w
- invalid remote image URL
- too many redirects
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/fb5efae879de2d52.
Report an issue: GitHub.