{"record":{"id":"425c1468dc6aa884","repo":"abiosoft/colima","slug":"error-parsing-sha-file-from-s-w","errorCode":null,"errorMessage":"error parsing SHA file from '%s': %w","messagePattern":"error parsing SHA file from '(.+?)': %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/downloader/sha.go","lineNumber":113,"sourceCode":"}\n\n// fetchSHAFromURL fetches SHA checksum file and extracts digest for the target file\nfunc fetchSHAFromURL(shaURL, targetFilename string) (string, error) {\n\tctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)\n\tdefer cancel()\n\n\tclient := NewHTTPClient()\n\n\t// fetch SHA file content\n\tdata, err := client.Fetch(ctx, shaURL)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"error downloading SHA file from '%s': %w\", shaURL, err)\n\t}\n\n\t// parse SHA file to find the matching entry\n\tdigest, err := parseSHAContent(data, targetFilename)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"error parsing SHA file from '%s': %w\", shaURL, err)\n\t}\n\n\treturn digest, nil\n}\n\n// parseSHAContent reads SHA checksum content and extracts the digest for the target filename.\n// Supports formats:\n//   - GNU coreutils: \"<hash>  <filename>\" (two spaces)\n//   - BSD/binary mode: \"<hash> *<filename>\" (space + asterisk)\nfunc parseSHAContent(data []byte, targetFilename string) (string, error) {\n\tscanner := bufio.NewScanner(bytes.NewReader(data))\n\tfor scanner.Scan() {\n\t\tline := scanner.Text()\n\t\t// format: \"<hash>  <filename>\" (two spaces) or \"<hash> *<filename>\" (binary mode)\n\t\tparts := strings.Fields(line)\n\t\tif len(parts) >= 2 {\n\t\t\thash := parts[0]\n\t\t\tfilename := strings.TrimPrefix(parts[len(parts)-1], \"*\")","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/abiosoft/colima/blob/c3a5f9184d83a197184f897a9f07eb3c01b3bc88/util/downloader/sha.go#L95-L131","documentation":"The checksum file downloaded fine but parseSHAContent failed while scanning it. The input is an in-memory []byte, so genuine read errors are essentially impossible — the realistic trigger is bufio.Scanner's ErrTooLong: a single line exceeding the default 64KB buffer. In practice the body is not a checksum file at all (binary payload or garbage served with a 200).","triggerScenarios":"Server returns binary data or one over-long line with HTTP 200 (misconfigured mirror, captive-portal/HTML page behind a 200, error blob); pathological checksum files with >64KB lines.","commonSituations":"CDN serving an HTML page with status 200 instead of the checksum file; checksum endpoints returning concatenated or binary data.","solutions":["curl the sha URL and inspect what the body actually contains","Fix the URL or the upstream content so a real checksum file is served","If it is a captive portal, fix network connectivity and retry"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"cacheFile, err := downloader.Download(host, req)\nif err != nil && strings.Contains(err.Error(), \"error parsing SHA file\") {\n    // body is not a checksum file: fetch it yourself and inspect\n    // curl -fsSL \"$SHA_URL\" | head\n    return fmt.Errorf(\"checksum url %q does not serve a parseable checksum file: %w\", req.SHA.URL, err)\n}","preventionTips":["Validate the checksum endpoint's content when onboarding a mirror","Watch for captive portals and CDN error pages served with status 200"],"tags":["sha","parsing","download","http"],"backgroundTag":null,"analyzedSha":"c3a5f9184d83a197184f897a9f07eb3c01b3bc88","analyzedAt":"2026-08-15T18:58:08.334Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}