{"record":{"id":"eda091a47391e64e","repo":"plandex-ai/plandex","slug":"error-encoding-custom-provider-v","errorCode":null,"errorMessage":"Error encoding custom provider: %v","messagePattern":"Error encoding custom provider: (.+?)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"app/server/handlers/models.go","lineNumber":424,"sourceCode":"\nfunc GetCustomProviderHandler(w http.ResponseWriter, r *http.Request) {\n\tauth := Authenticate(w, r, true)\n\tif auth == nil {\n\t\treturn\n\t}\n\n\tid := mux.Vars(r)[\"providerId\"]\n\n\tres, err := db.GetCustomProvider(auth.OrgId, id)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\terr = json.NewEncoder(w).Encode(res.ToApi())\n\tif err != nil {\n\t\tlog.Printf(\"Error encoding custom provider: %v\\n\", err)\n\t\thttp.Error(w, fmt.Sprintf(\"Error encoding custom provider: %v\", err), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tlog.Println(\"Successfully fetched custom provider\")\n}\n\nfunc ListCustomProvidersHandler(w http.ResponseWriter, r *http.Request) {\n\tauth := Authenticate(w, r, true)\n\tif auth == nil {\n\t\treturn\n\t}\n\n\tif os.Getenv(\"IS_CLOUD\") != \"\" {\n\t\thttp.Error(w, \"Custom model providers are not supported on Plandex Cloud\", http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tlist, err := db.ListCustomProviders(auth.OrgId)","sourceCodeStart":406,"sourceCodeEnd":442,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/models.go#L406-L442","documentation":"GetCustomProviderHandler encodes res.ToApi() into the response with json.NewEncoder(w).Encode; on failure it logs 'Error encoding custom provider' and returns 500. The JSON encoding of a CustomProvider rarely fails on data; the usual cause is the HTTP connection failing while the encoder writes (client gone, connection reset).","triggerScenarios":"GET custom provider where the client disconnects or the transport errors while the JSON body is written to the ResponseWriter.","commonSituations":"Client aborts the request right after it is issued; proxy timeout kills the upstream connection during the write; network drop on mobile clients.","solutions":["Check whether the requesting client actually received anything; a disconnect here is benign — retry the request.","Review proxy/load-balancer timeout configuration for premature connection closes.","If reproducible with healthy connections, inspect CustomProvider.ToApi() for newly added unmarshalable fields.","Marshal to a buffer before writing so encode errors are separated from transport write errors."],"exampleFix":"// before\nerr = json.NewEncoder(w).Encode(res.ToApi())\nif err != nil {\n    http.Error(w, fmt.Sprintf(\"Error encoding custom provider: %v\", err), http.StatusInternalServerError)\n}\n// after\nbuf, err := json.Marshal(res.ToApi())\nif err != nil {\n    http.Error(w, \"encoding failed\", http.StatusInternalServerError)\n    return\n}\nw.Header().Set(\"Content-Type\", \"application/json\")\nw.Write(buf)","handlingStrategy":"try-catch","validationCode":"// Caller: ensure a live connection and a non-cancelled context before requesting\nif r.Context().Err() != nil { return }\nreq, _ := http.NewRequestWithContext(r.Context(), \"GET\", providerURL, nil)","typeGuard":null,"tryCatchPattern":"if err := json.NewEncoder(w).Encode(res.ToApi()); err != nil {\n    log.Printf(\"Error encoding custom provider: %v\", err)\n    return // headers may already be sent; do not attempt http.Error after a partial write\n}","preventionTips":["Marshal to a buffer first, then a single w.Write, to isolate encode vs transport errors","Treat post-header write errors as transport noise, not 500-worthy server bugs","Configure proxies with timeouts longer than the handler's worst-case latency","Keep CustomProvider.ToApi() free of unmarshalable types"],"tags":["go","http","json-encoding","network"],"backgroundTag":"http-response-write-failed","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}