From f8b6aa6c97e20231fc91bed060330a7b2111de2f Mon Sep 17 00:00:00 2001 From: rcourtman Date: Wed, 22 Oct 2025 14:23:13 +0000 Subject: [PATCH] Treat 501 responses as non-fatal in cluster failover (#449) --- pkg/proxmox/cluster_client.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/pkg/proxmox/cluster_client.go b/pkg/proxmox/cluster_client.go index 41fc84a..c8915e3 100644 --- a/pkg/proxmox/cluster_client.go +++ b/pkg/proxmox/cluster_client.go @@ -515,6 +515,16 @@ func (cc *ClusterClient) executeWithFailover(ctx context.Context, fn func(*Clien return err } + if isNotImplementedError(errStr) { + // Endpoint not implemented on this node/version; bubble up without marking it unhealthy + log.Debug(). + Str("cluster", cc.name). + Str("endpoint", clientEndpoint). + Err(err). + Msg("Endpoint not implemented, not marking cluster node unhealthy") + return err + } + if isRateLimited, statusCode := isTransientRateLimitError(err); isRateLimited { backoff := calculateRateLimitBackoff(i) cc.applyRateLimitCooldown(clientEndpoint, backoff) @@ -628,6 +638,25 @@ func extractStatusCode(errStr string) int { return code } +func isNotImplementedError(errStr string) bool { + lower := strings.ToLower(errStr) + if !strings.Contains(lower, "not implemented") { + return false + } + + // Common formatting: "status 501", "error 501", "api error 501" + if strings.Contains(lower, " 501") || strings.Contains(lower, "status 501") || strings.Contains(lower, "error 501") { + return true + } + + // Fallback to explicit HTTP status detection + if extractStatusCode(errStr) == 501 { + return true + } + + return false +} + // GetHealthStatus returns the health status of all nodes func (cc *ClusterClient) GetHealthStatus() map[string]bool { cc.mu.RLock()