chenhg5/cc-connect · error

request upload url

Error message

request upload url: %w

What it means

This wraps a transport-level failure of the first step of the MAX two-step upload: the GET/POST to /uploads?type=<kind> that requests a temporary upload URL. The library did not even get an HTTP response — the request failed at the network layer (DNS, TLS, timeout, connection reset).

Solutions

  1. Check outbound network connectivity and DNS for the MAX API host from the deployment environment
  2. Inspect the wrapped error (%w) for context.DeadlineExceeded vs connection errors to decide retry vs abort
  3. Verify proxy/firewall settings allow HTTPS to the MAX API
  4. Retry transient network errors with backoff; propagate cancellation for user-initiated aborts

Example fix

// before
token, err := p.uploadAttachment(ctx, "file", data, name)
if err != nil { return err }
// after
token, err := p.uploadAttachment(ctx, "file", data, name)
if err != nil {
    if errors.Is(err, context.DeadlineExceeded) {
        return fmt.Errorf("max: upload timed out for %s (%d bytes)", name, len(data))
    }
    return err
}
Defensive patterns

Strategy: retry

Validate before calling

if err := ctx.Err(); err != nil { return err } // ensure context still alive before starting upload

Try / catch

var nerr net.Error
if errors.As(err, &nerr) && nerr.Timeout() {
    // retry with backoff, larger timeout
}
if errors.Is(err, context.Canceled) {
    return err // user aborted, do not retry
}

Prevention

When it happens

Trigger: SendImage/SendFile/SendAudio calling uploadAttachment when p.uploadClient.Do(urlReq) errors: no network, DNS failure, TLS error, context deadline exceeded (5-minute attachmentUploadTO or parent ctx cancelled), or upload client misconfigured proxy.

Common situations: Uploading large files from a container with no outbound internet; corporate proxy blocking bot-api host; user cancels the operation and the parent context is cancelled mid-upload; slow CDN causing the 5-minute timeout.

Related errors


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

Appendix: source

Thrown at platform/max/max.go:553

	}
	// Use a 5-minute context AND a dedicated http.Client with a matching Timeout.
	// p.client has a 35 s Timeout which fires independently of the context deadline
	// and would abort large CDN uploads before the context expires.
	uploadCtx, cancel := context.WithTimeout(ctx, attachmentUploadTO)
	defer cancel()

	urlReq, err := http.NewRequestWithContext(uploadCtx, http.MethodPost, p.apiBase+"/uploads", nil)
	if err != nil {
		return "", err
	}
	p.setAuth(urlReq)
	q := urlReq.URL.Query()
	q.Set("type", kind)
	urlReq.URL.RawQuery = q.Encode()

	urlResp, err := p.uploadClient.Do(urlReq)
	if err != nil {
		return "", fmt.Errorf("request upload url: %w", err)
	}
	defer urlResp.Body.Close()
	if urlResp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(io.LimitReader(urlResp.Body, 512))
		return "", fmt.Errorf("upload url: HTTP %d: %s", urlResp.StatusCode, body)
	}
	var urlInfo struct {
		URL   string `json:"url"`
		Token string `json:"token"`
	}
	if err := json.NewDecoder(urlResp.Body).Decode(&urlInfo); err != nil {
		return "", fmt.Errorf("decode upload url: %w", err)
	}
	if urlInfo.URL == "" {
		return "", fmt.Errorf("upload url: empty url in response")
	}

	if filename == "" {

View on GitHub (pinned to 4000b2338a)