{"record":{"id":"8281feebd0bccf6e","repo":"chenhg5/cc-connect","slug":"max-send-message-w","errorCode":null,"errorMessage":"max: send message: %w","messagePattern":"max: send message: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/max/max.go","lineNumber":1397,"sourceCode":"\tdata, err := json.Marshal(body)\n\tif err != nil {\n\t\treturn err\n\t}\n\tbackoff := attachmentReadyDelay\n\tfor attempt := 0; attempt <= attachmentReadyRetries; attempt++ {\n\t\treq, err := http.NewRequestWithContext(ctx, http.MethodPost, p.apiBase+\"/messages\", bytes.NewReader(data))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tp.setAuth(req)\n\t\tq := req.URL.Query()\n\t\tq.Set(\"chat_id\", chatID)\n\t\treq.URL.RawQuery = q.Encode()\n\t\treq.Header.Set(\"Content-Type\", \"application/json\")\n\n\t\tresp, err := p.client.Do(req)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"max: send message: %w\", err)\n\t\t}\n\t\trespBody, _ := io.ReadAll(io.LimitReader(resp.Body, 2048))\n\t\tresp.Body.Close()\n\n\t\tif resp.StatusCode == http.StatusOK {\n\t\t\treturn nil\n\t\t}\n\t\tif isAttachmentNotReady(respBody) && attempt < attachmentReadyRetries {\n\t\t\tslog.Debug(\"max: attachment not ready, retrying\", \"attempt\", attempt+1, \"backoff\", backoff)\n\t\t\tselect {\n\t\t\tcase <-ctx.Done():\n\t\t\t\treturn ctx.Err()\n\t\t\tcase <-time.After(backoff):\n\t\t\t}\n\t\t\tbackoff *= 2\n\t\t\tcontinue\n\t\t}\n\t\tslog.Warn(\"max: send message failed\", \"status\", resp.StatusCode, \"chat\", chatID, \"body\", string(respBody))","sourceCodeStart":1379,"sourceCodeEnd":1415,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/max/max.go#L1379-L1415","documentation":"The HTTP request that delivers the outbound message to the MAX send-message endpoint failed at the transport level; the underlying error is wrapped with %w. This happens before any status code is available.","triggerScenarios":"DNS failure, connection refused/reset, TLS errors, or context timeout/deadline exceeded while POSTing to p.apiBase-based send endpoint.","commonSituations":"No internet access or DNS misconfiguration on the host; MAX API outage; proxy/firewall blocking outbound HTTPS; overly aggressive timeout cancelling in-flight requests.","solutions":["Inspect the wrapped cause with errors.Unwrap / %v to see if it is DNS, connect, or timeout","Verify network connectivity and DNS for apiBase from the bot host","Check proxy env vars (HTTPS_PROXY) if behind a corporate proxy","Increase the send timeout or add retry with backoff for transient transport errors"],"exampleFix":"// before\nif err := p.client.Do(req); err != nil {\n\treturn fmt.Errorf(\"max: send message: %w\", err)\n}\n// after\nif err := p.client.Do(req); err != nil {\n\tif ctx.Err() != nil {\n\t\treturn fmt.Errorf(\"max: send message: canceled: %w\", ctx.Err())\n\t}\n\treturn fmt.Errorf(\"max: send message: %w\", err) // caller retries on net.Error\n}","handlingStrategy":"retry","validationCode":"if _, err := net.LookupHost(host(apiBase)); err != nil { failFast(\"MAX apiBase unresolvable\") }","typeGuard":null,"tryCatchPattern":"err := p.Send(ctx, chat, text)\nvar nerr net.Error\nif errors.As(err, &nerr) && nerr.Timeout() {\n\tctx2, c := context.WithTimeout(context.Background(), 15*time.Second)\n\tdefer c(); retryWith(ctx2)\n}","preventionTips":["Monitor host connectivity/DNS to apiBase","Set sane HTTP client timeouts and retry transient transport errors","Check HTTPS_PROXY settings on the bot host"],"tags":["network","http","send"],"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"}