{"record":{"id":"4f18c04719b498c9","repo":"chenhg5/cc-connect","slug":"request-upload-url-w","errorCode":null,"errorMessage":"request upload url: %w","messagePattern":"request upload url: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/max/max.go","lineNumber":553,"sourceCode":"\t}\n\t// Use a 5-minute context AND a dedicated http.Client with a matching Timeout.\n\t// p.client has a 35 s Timeout which fires independently of the context deadline\n\t// and would abort large CDN uploads before the context expires.\n\tuploadCtx, cancel := context.WithTimeout(ctx, attachmentUploadTO)\n\tdefer cancel()\n\n\turlReq, err := http.NewRequestWithContext(uploadCtx, http.MethodPost, p.apiBase+\"/uploads\", nil)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tp.setAuth(urlReq)\n\tq := urlReq.URL.Query()\n\tq.Set(\"type\", kind)\n\turlReq.URL.RawQuery = q.Encode()\n\n\turlResp, err := p.uploadClient.Do(urlReq)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"request upload url: %w\", err)\n\t}\n\tdefer urlResp.Body.Close()\n\tif urlResp.StatusCode != http.StatusOK {\n\t\tbody, _ := io.ReadAll(io.LimitReader(urlResp.Body, 512))\n\t\treturn \"\", fmt.Errorf(\"upload url: HTTP %d: %s\", urlResp.StatusCode, body)\n\t}\n\tvar urlInfo struct {\n\t\tURL   string `json:\"url\"`\n\t\tToken string `json:\"token\"`\n\t}\n\tif err := json.NewDecoder(urlResp.Body).Decode(&urlInfo); err != nil {\n\t\treturn \"\", fmt.Errorf(\"decode upload url: %w\", err)\n\t}\n\tif urlInfo.URL == \"\" {\n\t\treturn \"\", fmt.Errorf(\"upload url: empty url in response\")\n\t}\n\n\tif filename == \"\" {","sourceCodeStart":535,"sourceCodeEnd":571,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/max/max.go#L535-L571","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check outbound network connectivity and DNS for the MAX API host from the deployment environment","Inspect the wrapped error (%w) for context.DeadlineExceeded vs connection errors to decide retry vs abort","Verify proxy/firewall settings allow HTTPS to the MAX API","Retry transient network errors with backoff; propagate cancellation for user-initiated aborts"],"exampleFix":"// before\ntoken, err := p.uploadAttachment(ctx, \"file\", data, name)\nif err != nil { return err }\n// after\ntoken, err := p.uploadAttachment(ctx, \"file\", data, name)\nif err != nil {\n    if errors.Is(err, context.DeadlineExceeded) {\n        return fmt.Errorf(\"max: upload timed out for %s (%d bytes)\", name, len(data))\n    }\n    return err\n}","handlingStrategy":"retry","validationCode":"if err := ctx.Err(); err != nil { return err } // ensure context still alive before starting upload","typeGuard":null,"tryCatchPattern":"var nerr net.Error\nif errors.As(err, &nerr) && nerr.Timeout() {\n    // retry with backoff, larger timeout\n}\nif errors.Is(err, context.Canceled) {\n    return err // user aborted, do not retry\n}","preventionTips":["Use a context with adequate deadline for large uploads (the lib uses 5 minutes)","Confirm egress/proxy allows HTTPS to the MAX API host from production","Distinguish cancellation (do not retry) from timeouts (retry) via errors.Is/As","Set sensible http.Client timeouts on custom clients"],"tags":["network","upload","timeout","max"],"backgroundTag":"network-request-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}