{"record":{"id":"545905e0dd277faa","repo":"chenhg5/cc-connect","slug":"http-d","errorCode":null,"errorMessage":"HTTP %d","messagePattern":"HTTP %d","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/cc-connect/tuitui.go","lineNumber":183,"sourceCode":"\tprintJSON(map[string]any{\n\t\t\"ok\":         true,\n\t\t\"channel_id\": opts.channelID,\n\t\t\"parent_id\":  opts.parentID,\n\t})\n}\n\nfunc downloadTuiTuiURL(ctx context.Context, rawURL string, maxBytes int64) ([]byte, string, string, error) {\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, rawURL, nil)\n\tif err != nil {\n\t\treturn nil, \"\", \"\", err\n\t}\n\tresp, err := http.DefaultClient.Do(req)\n\tif err != nil {\n\t\treturn nil, \"\", \"\", err\n\t}\n\tdefer func() { _ = resp.Body.Close() }()\n\tif resp.StatusCode < 200 || resp.StatusCode >= 300 {\n\t\treturn nil, \"\", \"\", fmt.Errorf(\"HTTP %d\", resp.StatusCode)\n\t}\n\tlimit := maxBytes\n\tif limit <= 0 {\n\t\tlimit = 25 << 20\n\t}\n\tif resp.ContentLength > limit {\n\t\treturn nil, \"\", \"\", fmt.Errorf(\"download exceeds --max-bytes: %d > %d\", resp.ContentLength, limit)\n\t}\n\tdata, err := io.ReadAll(io.LimitReader(resp.Body, limit+1))\n\tif err != nil {\n\t\treturn nil, \"\", \"\", err\n\t}\n\tif int64(len(data)) > limit {\n\t\treturn nil, \"\", \"\", fmt.Errorf(\"download exceeds --max-bytes: %d > %d\", len(data), limit)\n\t}\n\tmimeType := resp.Header.Get(\"Content-Type\")\n\tif mimeType == \"\" || mimeType == \"application/octet-stream\" {\n\t\tmimeType = http.DetectContentType(data)","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/cmd/cc-connect/tuitui.go#L165-L201","documentation":"downloadTuiTuiURL performs an HTTP GET via http.DefaultClient and rejects any response whose status code falls outside the 200-299 range. The error is a bare status code (e.g. \"HTTP 404\") with no body, so the actual server reason is lost. It exists to fail fast before reading a non-success response body.","triggerScenarios":"The remote TuiTui URL (rawURL) responds with 3xx-treated-as-error status or 4xx/5xx — e.g. a dead file link, expired signed URL, private/repo-removed asset, or the URL redirects to an endpoint returning 403/404. Called via runTuiTuiDownload with --url.","commonSituations":"Downloading a release asset whose tag/URL changed; Gitee/GitHub raw URL for a private repo without auth; typo'd URL; server temporarily down (502/503).","solutions":["Check the exact status code in the message and open the URL in a browser/curl to see the real response","Fix the --url value (wrong tag, renamed file, removed release)","If the asset requires auth, add the token to the URL or use an authenticated fetch path","Retry if the code is 5xx (transient server error)"],"exampleFix":"// before: opaque error without body\nreturn nil, \"\", \"\", fmt.Errorf(\"HTTP %d\", resp.StatusCode)\n// after: include status text and a body snippet for diagnosis\nbody, _ := io.ReadAll(io.LimitReader(resp.Body, 512))\nreturn nil, \"\", \"\", fmt.Errorf(\"download %s: HTTP %d: %s\", rawURL, resp.StatusCode, string(body))","handlingStrategy":"validation","validationCode":"resp, err := http.Head(rawURL)\nif err != nil || (resp.StatusCode < 200 || resp.StatusCode >= 300) {\n\treturn fmt.Errorf(\"URL not downloadable: HTTP %v\", err)\n}","typeGuard":"func is2xx(code int) bool { return code >= 200 && code < 300 }","tryCatchPattern":"data, _, _, err := downloadTuiTuiURL(ctx, rawURL, 0)\nif err != nil {\n\tvar httpErr = err\n\tslog.Warn(\"tuitui download failed\", \"err\", httpErr)\n\treturn fmt.Errorf(\"download failed (%w); verify the URL is reachable\", err)\n}","preventionTips":["curl -I the URL before automating downloads","Pin release asset URLs to immutable tags, not moving branches","Handle private assets with authenticated requests","Treat 5xx as retryable with backoff"],"tags":["http","network","download","cli"],"backgroundTag":"http-error-response","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}