{"record":{"id":"9ba90fef073248b4","repo":"chenhg5/cc-connect","slug":"http-get-s-status-d-9ba90f","errorCode":null,"errorMessage":"HTTP GET %s: status %d","messagePattern":"HTTP GET (.+?): status (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/skill_presets.go","lineNumber":128,"sourceCode":"\t\treturn nil, fmt.Errorf(\"fetch skill presets: %w\", err)\n\t}\n\n\tc.data = result\n\tc.fetchedAt = time.Now()\n\treturn c.data, nil\n}\n\nfunc fetchSkillPresetsFromURL(url string, timeout time.Duration) (*SkillPresetsResponse, error) {\n\tslog.Debug(\"fetching skill presets\", \"url\", url)\n\tclient := &http.Client{Timeout: timeout}\n\tresp, err := client.Get(url)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"HTTP GET %s: %w\", url, err)\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"HTTP GET %s: status %d\", url, resp.StatusCode)\n\t}\n\n\tbody, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"read body from %s: %w\", url, err)\n\t}\n\n\tvar result SkillPresetsResponse\n\tif err := json.Unmarshal(body, &result); err != nil {\n\t\treturn nil, fmt.Errorf(\"parse JSON from %s: %w\", url, err)\n\t}\n\treturn &result, nil\n}\n","sourceCodeStart":110,"sourceCodeEnd":142,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/skill_presets.go#L110-L142","documentation":"fetchSkillPresetsFromURL throws this when the HTTP response completes but the status code is not 200 OK. It is a non-2xx guard: 404 for a moved presets file, 403 for blocked access, 5xx for server trouble — the status is embedded in the message along with the URL.","triggerScenarios":"GETting a skill presets URL that returns 404 (file renamed/moved), 403 (rate limit, geo/UA block, missing auth), 301/302 that Go followed to a non-200 endpoint, or 5xx during a server incident.","commonSituations":"Preset source URL pinned to an old version path that no longer exists; CDN blocking the default Go User-Agent; mirror returning 503 under load.","solutions":["Check the logged status code: 404 → update the URL to the current presets location; 403 → check auth/UA requirements; 5xx → retry later","curl -I the URL to confirm the status outside the app","Replace the dead source with a maintained mirror; with multiple sources configured, fetch succeeds if any one returns 200","If the source requires a token, switch to a source URL that includes authorized access"],"exampleFix":"// before\nurl = \"https://example.com/skills-presets-v1.json\"   // 404\n// after\nurl = \"https://example.com/skills-presets-v2.json\"   // verify: curl -I returns 200","handlingStrategy":"retry","validationCode":"resp, err := http.Head(sourceURL)\nif err == nil && resp.StatusCode != http.StatusOK {\n    return fmt.Errorf(\"presets source unhealthy: %s returns %d\", sourceURL, resp.StatusCode)\n}","typeGuard":null,"tryCatchPattern":"presets, err := fetchSkillPresetsFromURL(url, timeout)\nif err != nil {\n    var statusErr interface{ Error() string }\n    if strings.Contains(err.Error(), \"status \") { // e.g. \"HTTP GET ...: status 404\"\n        slog.Warn(\"presets source returned non-200; trying next source\", \"url\", url, \"err\", err)\n    }\n    _ = statusErr\n}","preventionTips":["Pin preset URLs to maintained, versioned raw-JSON locations and update them on upstream renames","Check status codes: 404 → fix path; 403 → check auth/UA/rate limits; 5xx → retry later","Configure several sources so a single non-200 source doesn't break presets loading"],"tags":["http","http-status","network"],"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-14T05:17:10.506Z"}