{"record":{"id":"a9999ec593e6d164","repo":"plandex-ai/plandex","slug":"apierr-msg","errorCode":null,"errorMessage":"{apiErr.Msg}","messagePattern":"\\{apiErr\\.Msg\\}","errorType":"http","errorClass":"shared.ApiError","httpStatus":null,"severity":"error","filePath":"app/server/routes/routes.go","lineNumber":37,"sourceCode":"\nfunc RegisterHandlePlandex(fn HandlePlandex) {\n\tHandlePlandexFn = fn\n}\n\nfunc EnsureHandlePlandex() {\n\tif HandlePlandexFn == nil {\n\t\tpanic(\"handlePlandexFn is not set\")\n\t}\n}\n\nfunc AddHealthRoutes(r *mux.Router) {\n\tEnsureHandlePlandex()\n\n\tHandlePlandexFn(r, \"/health\", false, func(w http.ResponseWriter, r *http.Request) {\n\t\t_, apiErr := hooks.ExecHook(hooks.HealthCheck, hooks.HookParams{})\n\t\tif apiErr != nil {\n\t\t\tlog.Printf(\"Error in health check hook: %v\\n\", apiErr)\n\t\t\thttp.Error(w, apiErr.Msg, apiErr.Status)\n\t\t\treturn\n\t\t}\n\t\tfmt.Fprint(w, \"OK\")\n\t})\n\n\tHandlePlandexFn(r, \"/version\", false, func(w http.ResponseWriter, r *http.Request) {\n\t\t// Log the host\n\t\thost := r.Host\n\t\tlog.Printf(\"Host header: %s\", host)\n\n\t\texecPath, err := os.Executable()\n\t\tif err != nil {\n\t\t\tlog.Fatal(\"Error getting current directory: \", err)\n\t\t}\n\t\tcurrentDir := filepath.Dir(execPath)\n\n\t\t// get version from version.txt\n\t\tvar path string","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/routes/routes.go#L19-L55","documentation":"This is the /health endpoint of the Plandex server surfacing a failure from the hooks.HealthCheck hook. When ExecHook returns a non-nil apiErr, the handler logs it and writes apiErr.Msg with apiErr.Status back to the client. The error means a registered health-check hook failed, so the server is reporting itself unhealthy.","triggerScenarios":"Any registered hooks.HealthCheck hook returns an api.ApiError: typically a failed internal dependency check (e.g. database unreachable, migration failure, or another subsystem the hook probes) during GET /health.","commonSituations":"Load balancers or Kubernetes liveness/readiness probes hitting /health while the database is down or misconfigured; starting the server before its backing services are ready; broken hook registration after upgrades.","solutions":["Check the server logs for 'Error in health check hook' to see the underlying hook error and its cause","Verify the dependencies probed by the health-check hook (database, external services) are reachable and credentials are correct","Retry /health once dependencies are restored; the message is per-request, not sticky","If the hook itself is buggy, inspect hooks.ExecHook(hooks.HealthCheck) implementations and fix or unregister the failing hook"],"exampleFix":"// before\n_, apiErr := hooks.ExecHook(hooks.HealthCheck, hooks.HookParams{})\nif apiErr != nil {\n\thttp.Error(w, apiErr.Msg, apiErr.Status)\n\treturn\n}\n// after\n_, apiErr := hooks.ExecHook(hooks.HealthCheck, hooks.HookParams{})\nif apiErr != nil {\n\tlog.Printf(\"health check failed: %v (msg=%s status=%d)\", apiErr, apiErr.Msg, apiErr.Status)\n\thttp.Error(w, apiErr.Msg, apiErr.Status)\n\treturn\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"resp, err := http.Get(serverURL + \"/health\")\nif err != nil {\n\t// server unreachable entirely\n\treturn err\n}\ndefer resp.Body.Close()\nif resp.StatusCode != http.StatusOK {\n\tbody, _ := io.ReadAll(resp.Body)\n\treturn fmt.Errorf(\"health check failed (status %d): %s\", resp.StatusCode, string(body))\n}","preventionTips":["Use the HTTP status code from /health as the health signal, not just connection success","Monitor server logs for 'Error in health check hook' to catch dependency failures early","Configure orchestrator probes with a small retry/period so transient dependency blips don't kill the server","Keep health-check hook dependencies (DB DSN, service endpoints) in validated startup config"],"tags":["go","http","health-check","server"],"backgroundTag":"health-check-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"}