@@ -2,7 +2,6 @@ package handlers
22
33import (
44 "context"
5- "errors"
65 "log/slog"
76 "sync"
87 "time"
@@ -59,68 +58,6 @@ func waitWithDeadline(wg *sync.WaitGroup, cancel context.CancelFunc, deadline ti
5958 return WaitWithDeadline (wg , cancel , deadline )
6059}
6160
62- // sanitizedErrorMessages maps error types to user-friendly messages that do
63- // not expose internal infrastructure details (#4753).
64- var sanitizedErrorMessages = map [string ]string {
65- "network" : "Cluster is unreachable — check network connectivity" ,
66- "auth" : "Authentication to cluster failed — check credentials" ,
67- "timeout" : "Cluster request timed out — the cluster may be overloaded or unreachable" ,
68- "certificate" : "TLS certificate error — check cluster certificate configuration" ,
69- }
70-
71- // handleK8sError inspects a Kubernetes API error and returns the appropriate
72- // HTTP response. Cluster-connectivity errors (network, auth, timeout,
73- // certificate) are returned as 200 with a "clusterStatus":"unavailable"
74- // payload so the frontend can show a degraded state instead of a broken page.
75- // All other errors are returned as 500 Internal Server Error.
76- // Raw error details are only logged server-side and never sent to the client (#4753).
77- func HandleK8sError (c * fiber.Ctx , err error ) error {
78- if errors .Is (err , k8s .ErrNoClusterConfigured ) {
79- slog .Info ("[MCP] no cluster configured" )
80- return ErrNoClusterAccess (c )
81- }
82-
83- errType := k8s .ClassifyError (err .Error ())
84- switch errType {
85- case "not_found" :
86- // Invalid or non-existent cluster — return 404 with consistent error format (#4907, #4908)
87- slog .Info ("[MCP] cluster not found" , "errorType" , errType , "error" , err )
88- return c .Status (fiber .StatusNotFound ).JSON (fiber.Map {
89- "clusterStatus" : "not_found" ,
90- "errorType" : errType ,
91- "errorMessage" : "Cluster not found — verify the cluster name exists in your kubeconfig" ,
92- })
93- case "network" , "auth" , "timeout" , "certificate" :
94- // Cluster exists but is unreachable — return 503 with consistent error format (#4908)
95- slog .Info ("[MCP] cluster unavailable" , "errorType" , errType , "error" , err )
96- return c .Status (fiber .StatusServiceUnavailable ).JSON (fiber.Map {
97- "clusterStatus" : "unavailable" ,
98- "errorType" : errType ,
99- "errorMessage" : sanitizedErrorMessages [errType ],
100- })
101- default :
102- slog .Error ("[MCP] internal error" , "error" , err )
103- return c .Status (fiber .StatusInternalServerError ).JSON (fiber.Map {
104- "clusterStatus" : "error" ,
105- "errorType" : "internal" ,
106- "errorMessage" : "An internal error occurred" ,
107- })
108- }
109- }
110-
111- func handleK8sError (c * fiber.Ctx , err error ) error {
112- return HandleK8sError (c , err )
113- }
114-
115- // ClusterError represents a per-cluster failure in a multi-cluster request (#4758).
116- // Included in the response so the frontend can distinguish "no resources" from
117- // "cluster failed" and display an appropriate degraded-state indicator.
118- type ClusterError struct {
119- Cluster string `json:"cluster"`
120- ErrorType string `json:"errorType"`
121- Message string `json:"message"`
122- }
123-
12461// clusterErrorTracker collects per-cluster failures during multi-cluster
12562// fan-out operations. Thread-safe via its own mutex.
12663type clusterErrorTracker struct {
@@ -130,7 +67,7 @@ type clusterErrorTracker struct {
13067
13168func (t * clusterErrorTracker ) add (cluster string , err error ) {
13269 errType := k8s .ClassifyError (err .Error ())
133- msg , ok := sanitizedErrorMessages [errType ]
70+ msg , ok := SanitizedErrorMessages [errType ]
13471 if ! ok {
13572 msg = "An internal error occurred"
13673 }
0 commit comments