fix: improve handling of offline nodes and 595 errors

addresses #379 - better handling of offline nodes in clusters
- Skip polling VMs/containers from offline nodes to avoid 595 errors
- Improved error message for 595 to distinguish between auth failures and offline node access

addresses #389 - improved error messaging
- Better detection of whether 595 is an auth issue or offline node issue
- Clearer error messages to help users diagnose the actual problem

The 595 error can occur when:
1. Authentication actually fails (wrong credentials)
2. Trying to access resources on an offline node through another node in the cluster
This commit is contained in:
Pulse Monitor
2025-08-30 11:27:35 +00:00
parent c57c296cba
commit 38e49f77ac
2 changed files with 26 additions and 2 deletions
+18
View File
@@ -1268,6 +1268,15 @@ func (m *Monitor) pollVMs(ctx context.Context, instanceName string, client PVECl
func (m *Monitor) pollVMsWithNodes(ctx context.Context, instanceName string, client PVEClientInterface, nodes []proxmox.Node) {
var allVMs []models.VM
for _, node := range nodes {
// Skip offline nodes to avoid 595 errors when trying to access their resources
if node.Status != "online" {
log.Debug().
Str("node", node.Node).
Str("status", node.Status).
Msg("Skipping offline node for VM polling")
continue
}
vms, err := client.GetVMs(ctx, node.Node)
if err != nil {
monErr := errors.NewMonitorError(errors.ErrorTypeAPI, "get_vms", instanceName, err).WithNode(node.Node)
@@ -1579,6 +1588,15 @@ func (m *Monitor) pollContainersWithNodes(ctx context.Context, instanceName stri
var allContainers []models.Container
for _, node := range nodes {
// Skip offline nodes to avoid 595 errors when trying to access their resources
if node.Status != "online" {
log.Debug().
Str("node", node.Node).
Str("status", node.Status).
Msg("Skipping offline node for container polling")
continue
}
containers, err := client.GetContainers(ctx, node.Node)
if err != nil {
monErr := errors.NewMonitorError(errors.ErrorTypeAPI, "get_containers", instanceName, err).WithNode(node.Node)
+8 -2
View File
@@ -268,8 +268,14 @@ func (c *Client) request(ctx context.Context, method, path string, data url.Valu
// Special case for 403 with API token - this is usually a permission issue
err = fmt.Errorf("API error 403 (Forbidden): The API token does not have sufficient permissions. Note: In Proxmox GUI, permissions must be set on the USER (not just the token). Please verify the user '%s@%s' has the required permissions", c.auth.user, c.auth.realm)
} else if resp.StatusCode == 595 {
// 595 is Proxmox "no ticket" error - usually means authentication failed
err = fmt.Errorf("API error 595: Authentication failed - please check your credentials")
// 595 can mean authentication failed OR trying to access an offline node in a cluster
// Check if this is a node-specific endpoint
if strings.Contains(req.URL.Path, "/nodes/") && strings.Count(req.URL.Path, "/") > 3 {
// This looks like a node-specific resource request
err = fmt.Errorf("API error 595: Cannot access node resource - node may be offline or credentials may be invalid")
} else {
err = fmt.Errorf("API error 595: Authentication failed - please check your credentials")
}
} else if resp.StatusCode == 401 {
err = fmt.Errorf("API error 401 (Unauthorized): Invalid credentials or token")
} else {