{"record":{"id":"d56fec39de08bcc6","repo":"geektutu/7days-golang","slug":"err-error","errorCode":null,"errorMessage":"err.Error()","messagePattern":"err\\.Error\\(\\)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"gee-cache/day3-http-server/geecache/http.go","lineNumber":56,"sourceCode":"\t// /<basepath>/<groupname>/<key> required\n\tparts := strings.SplitN(r.URL.Path[len(p.basePath):], \"/\", 2)\n\tif len(parts) != 2 {\n\t\thttp.Error(w, \"bad request\", http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tgroupName := parts[0]\n\tkey := parts[1]\n\n\tgroup := GetGroup(groupName)\n\tif group == nil {\n\t\thttp.Error(w, \"no such group: \"+groupName, http.StatusNotFound)\n\t\treturn\n\t}\n\n\tview, err := group.Get(key)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tw.Header().Set(\"Content-Type\", \"application/octet-stream\")\n\tw.Write(view.ByteSlice())\n}\n","sourceCodeStart":38,"sourceCodeEnd":63,"githubUrl":"https://github.com/geektutu/7days-golang/blob/cf3644382101dc13e7fd92e8f5c66cabc51bcd3b/gee-cache/day3-http-server/geecache/http.go#L38-L63","documentation":"The group was found but group.Get(key) returned an error; ServeHTTP forwards err.Error() verbatim with HTTP 500. This is a pass-through of the underlying failure — usually the GetterFunc (cache-miss callback) failed, or a peer fetch/ConsistentHash call errored.","triggerScenarios":"Any group.Get(key) failure: the GetterFunc returns an error (DB down, record missing with an error return), the peer HTTP round-trip fails in remote-node mode, or the underlying byteview fetch errors.","commonSituations":"Backend database unreachable; GetterFunc logic bug (nil result marshaling); network partition between cache nodes; the peer selected by consistent hashing is down.","solutions":["Check the 500 response body — it contains the real underlying error message from group.Get.","Fix or harden the GetterFunc: return a sensible sentinel for 'not found' and log backend failures.","Verify peer connectivity (gee-cache/day5 peers) and retry the request if a peer was temporarily down.","Add timeouts/retries around external calls inside your GetterFunc so transient failures don't surface as raw 500s."],"exampleFix":"// before: getter returns raw DB error\ngeecache.GetterFunc(func(key string) ([]byte, error) {\n    return db.QueryRow(\"SELECT v FROM t WHERE k=?\", key) // misuse\n})\n// after: load bytes and return a clean error\ngeecache.GetterFunc(func(key string) ([]byte, error) {\n    var v []byte\n    if err := db.QueryRow(\"SELECT v FROM t WHERE k=?\", key).Scan(&v); err != nil {\n        return nil, fmt.Errorf(\"backend load %q: %w\", key, err)\n    }\n    return v, nil\n})","handlingStrategy":"try-catch","validationCode":"// pre-flight: verify backend the getter depends on is reachable\nif err := db.Ping(); err != nil {\n    return fmt.Errorf(\"cache getter backend unavailable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"// Go: handle 500 from the cache HTTP API with the forwarded error body\nresp, err := http.Get(url)\nif err != nil {\n    return err\n}\nif resp.StatusCode == http.StatusInternalServerError {\n    body, _ := io.ReadAll(resp.Body)\n    return fmt.Errorf(\"geecache get failed: %s\", body) // contains err.Error() from server\n}","preventionTips":["Wrap GetterFunc internals with timeouts and retries so transient failures don't surface as 500s.","Log the underlying error server-side; the HTTP body is your best diagnostic — read it.","Distinguish 'not found' (return empty/OK) from real backend errors in the getter.","Monitor 500 rates from cache endpoints to catch peer/DB outages early."],"tags":["http","cache","internal-server-error","getter"],"backgroundTag":"cache-getter-failed","analyzedSha":"cf3644382101dc13e7fd92e8f5c66cabc51bcd3b","analyzedAt":"2026-09-03T18:31:24.087Z","contentChangedAt":"2026-09-03T18:31:24.087Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}