{"record":{"id":"5f01a840a96e9484","repo":"plandex-ai/plandex","slug":"failed-to-fetch-custom-models","errorCode":null,"errorMessage":"Failed to fetch custom models: ","messagePattern":"Failed to fetch custom models: ","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"app/server/handlers/models.go","lineNumber":388,"sourceCode":"\tlog.Println(\"Successfully fetched custom model\")\n}\n\nfunc ListCustomModelsHandler(w http.ResponseWriter, r *http.Request) {\n\tlog.Println(\"Received request for ListCustomModelsHandler\")\n\n\tauth := Authenticate(w, r, true)\n\tif auth == nil {\n\t\treturn\n\t}\n\n\tif !requireMinClientVersion(w, r, CustomModelsMinClientVersion) {\n\t\treturn\n\t}\n\n\tmodels, err := db.ListCustomModels(auth.OrgId)\n\tif err != nil {\n\t\tlog.Printf(\"Error fetching custom models: %v\\n\", err)\n\t\thttp.Error(w, \"Failed to fetch custom models: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tvar apiList []*shared.CustomModel\n\tfor _, m := range models {\n\t\tapiList = append(apiList, m.ToApi())\n\t}\n\n\terr = json.NewEncoder(w).Encode(apiList)\n\tif err != nil {\n\t\tlog.Printf(\"Error encoding custom models: %v\\n\", err)\n\t\thttp.Error(w, fmt.Sprintf(\"Error encoding custom models: %v\", err), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tlog.Println(\"Successfully fetched custom models\")\n}\n","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/models.go#L370-L406","documentation":"ListCustomModelsHandler calls db.ListCustomModels(auth.OrgId) to enumerate an org's custom models; if the DB layer returns an error the handler logs it and responds 500 'Failed to fetch custom models: <err>'. This indicates the backing database read for that org failed, not a client input problem.","triggerScenarios":"Calling GET /custom models when db.ListCustomModels fails: database unreachable, query error, connection pool exhaustion, schema mismatch, or missing table.","commonSituations":"Database container down or restarted; migration not applied so the custom_models table/columns are missing; connection string/env var misconfigured in a new environment; pool exhausted under load.","solutions":["Read the logged 'Error fetching custom models: ...' detail — it contains the underlying DB error.","Verify DB connectivity from the server (ping, connection string/env config like DB host/port/user).","Confirm migrations ran and the custom models table/schema matches what db.ListCustomModels expects.","Check connection pool limits and DB logs for max_connections or timeout errors under load."],"exampleFix":"// before\nhttp.Error(w, \"Failed to fetch custom models: \"+err.Error(), http.StatusInternalServerError)\n// after\nif errors.Is(err, sql.ErrNoRows) || strings.Contains(err.Error(), \"does not exist\") {\n    http.Error(w, \"custom models schema missing; run migrations\", http.StatusInternalServerError)\n} else {\n    log.Printf(\"Error fetching custom models: %v\\n\", err)\n    http.Error(w, \"Failed to fetch custom models\", http.StatusInternalServerError) // avoid leaking DB details\n}","handlingStrategy":"retry","validationCode":"// Caller-side precheck: confirm the service is reachable and authenticated before listing\nresp, err := http.Get(baseURL + \"/healthz\")\nif err != nil || resp.StatusCode != 200 {\n    return fmt.Errorf(\"models service unavailable: %v\", err)\n}","typeGuard":null,"tryCatchPattern":"models, err := db.ListCustomModels(orgId)\nif err != nil {\n    if isTransient(err) { // net.Error timeout, driver conn errors\n        // retry once with backoff\n    }\n    log.Printf(\"Error fetching custom models: %v\", err)\n    http.Error(w, \"Failed to fetch custom models\", http.StatusInternalServerError)\n    return\n}","preventionTips":["Ensure migrations run on deploy so the custom models table always exists","Monitor DB health and pool saturation; alert on connection errors","Validate DB connection env vars in every environment before startup","Wrap transient DB errors with retry/backoff instead of failing the request immediately"],"tags":["go","database","http"],"backgroundTag":"database-query-failed","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}