{"record":{"id":"f839006560781c7a","repo":"abiosoft/colima","slug":"failed-to-decode-response-w","errorCode":null,"errorMessage":"failed to decode response: %w","messagePattern":"failed to decode response: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"model/ramalama.go","lineNumber":57,"sourceCode":"\n// getLatestRamalamaVersion fetches the latest release version from GitHub.\nfunc getLatestRamalamaVersion() (string, error) {\n\tclient := &http.Client{Timeout: 10 * time.Second}\n\tresp, err := client.Get(ramalamaReleasesURL)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to fetch releases: %w\", err)\n\t}\n\tdefer func() { _ = resp.Body.Close() }()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn \"\", fmt.Errorf(\"unexpected status code: %d\", resp.StatusCode)\n\t}\n\n\tvar release struct {\n\t\tTagName string `json:\"tag_name\"`\n\t}\n\tif err := json.NewDecoder(resp.Body).Decode(&release); err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to decode response: %w\", err)\n\t}\n\n\t// Tag might be \"v0.17.1\" or \"0.17.1\"\n\tversion := strings.TrimPrefix(release.TagName, \"v\")\n\treturn version, nil\n}\n\n// ramalamaModel represents a model from ramalama ls --json output.\ntype ramalamaModel struct {\n\tName     string `json:\"name\"`\n\tModified string `json:\"modified\"`\n\tSize     int64  `json:\"size\"`\n}\n\n// listRamalamaModels returns all locally available ramalama models.\nfunc listRamalamaModels() ([]ramalamaModel, error) {\n\tguest := lima.New(host.New())\n\toutput, err := guest.RunOutput(\"sh\", \"-c\", `export PATH=\"$HOME/.local/bin:$PATH\"; ramalama ls --json 2>/dev/null`)","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/abiosoft/colima/blob/c3a5f9184d83a197184f897a9f07eb3c01b3bc88/model/ramalama.go#L39-L75","documentation":"json.NewDecoder(resp.Body).Decode failed while parsing a 200 response from the GitHub releases endpoint into a struct holding only tag_name. Because the status check has already passed, the body received was not the expected JSON — typically an HTML captive-portal/proxy page or a truncated payload. %w chains the underlying *json.SyntaxError or *json.UnmarshalTypeError.","triggerScenarios":"A captive portal or HTTPS-inspecting proxy answers 200 with an HTML page; the connection drops mid-body so decoding hits unexpected EOF; a gateway returns 200 with an empty or fragmentary payload.","commonSituations":"Hotel/airport WiFi captive portals; corporate SSL-MITM appliances; flaky links that truncate responses before the JSON completes.","solutions":["Fetch the releases URL manually with curl from the same host and inspect the body actually returned","Configure or bypass HTTP(S) proxies for api.github.com (HTTPS_PROXY, NO_PROXY) so the JSON reaches the client","Retry the command — truncated bodies from transient faults usually decode fine on a second attempt"],"exampleFix":"// before\nif err := json.NewDecoder(resp.Body).Decode(&release); err != nil {\n\treturn \"\", fmt.Errorf(\"failed to decode response: %w\", err)\n}\n\n// after\nbody, err := io.ReadAll(resp.Body)\nif err != nil {\n\treturn \"\", fmt.Errorf(\"failed to read response: %w\", err)\n}\nif err := json.Unmarshal(body, &release); err != nil {\n\tsnippet := string(body)\n\tif len(snippet) > 120 {\n\t\tsnippet = snippet[:120]\n\t}\n\treturn \"\", fmt.Errorf(\"failed to decode response %q: %w\", snippet, err)\n}","handlingStrategy":"try-catch","validationCode":"// verify the endpoint really returns JSON before depending on the decode\nresp, err := http.Get(releasesURL)\nif err == nil && resp.Header.Get(\"Content-Type\") != \"application/json\" {\n\t// proxy/portal interference: do not attempt the decode\n}","typeGuard":null,"tryCatchPattern":"var syntaxErr *json.SyntaxError\nvar typeErr *json.UnmarshalTypeError\nswitch {\ncase errors.As(err, &syntaxErr):\n\t// body was not JSON at all (proxy/portal page): inspect connectivity\ncase errors.As(err, &typeErr):\n\t// JSON arrived but the shape changed: parser needs updating\ndefault:\n\t// unexpected EOF mid-body: retry once\n}","preventionTips":["Check the Content-Type header is application/json before decoding","Route api.github.com around TLS-inspecting proxies","Keep a cached last-known version so decode failures degrade instead of aborting"],"tags":["json","parsing","proxy","network","go"],"backgroundTag":null,"analyzedSha":"c3a5f9184d83a197184f897a9f07eb3c01b3bc88","analyzedAt":"2026-08-15T18:58:08.334Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}