diff --git a/internal/monitoring/monitor_polling.go b/internal/monitoring/monitor_polling.go index b609347..a44c687 100644 --- a/internal/monitoring/monitor_polling.go +++ b/internal/monitoring/monitor_polling.go @@ -513,6 +513,8 @@ func (m *Monitor) pollVMsWithNodes(ctx context.Context, instanceName string, cli Str("error", errStr). Msg("Failed to get VM filesystem info from guest agent") + // Classify the error type for better user messaging + // Order matters: check most specific patterns first if strings.Contains(errStr, "QEMU guest agent is not running") { diskStatusReason = "agent-not-running" log.Info(). @@ -520,10 +522,36 @@ func (m *Monitor) pollVMsWithNodes(ctx context.Context, instanceName string, cli Str("vm", vm.Name). Int("vmid", vm.VMID). Msg("Guest agent enabled in VM config but not running inside guest OS. Install and start qemu-guest-agent in the VM") - } else if strings.Contains(err.Error(), "timeout") { + } else if strings.Contains(errStr, "timeout") { diskStatusReason = "agent-timeout" - } else if strings.Contains(err.Error(), "permission denied") || strings.Contains(err.Error(), "not allowed") { + } else if strings.Contains(errStr, "500") && (strings.Contains(errStr, "not running") || strings.Contains(errStr, "not available")) { + // Proxmox API error 500 with "not running"/"not available" indicates guest agent issue, not permissions + // This commonly happens when guest agent is not installed or not running + diskStatusReason = "agent-not-running" + log.Info(). + Str("instance", instanceName). + Str("vm", vm.Name). + Int("vmid", vm.VMID). + Msg("Guest agent communication failed (API error 500). Install and start qemu-guest-agent in the VM") + } else if (strings.Contains(errStr, "403") || strings.Contains(errStr, "401")) && + (strings.Contains(strings.ToLower(errStr), "permission") || strings.Contains(strings.ToLower(errStr), "forbidden") || strings.Contains(strings.ToLower(errStr), "not allowed")) { + // Only treat as permission-denied if we get explicit auth/permission error codes (401/403) + // This distinguishes actual permission issues from guest agent unavailability diskStatusReason = "permission-denied" + log.Warn(). + Str("instance", instanceName). + Str("vm", vm.Name). + Int("vmid", vm.VMID). + Msg("Permission denied accessing guest agent. Verify Pulse user has VM.Monitor (PVE 8) or VM.Audit+VM.GuestAgent.Audit (PVE 9) permissions") + } else if strings.Contains(errStr, "500") { + // Generic 500 error without clear indicators - likely agent unavailable + // Refs #596: Proxmox returns 500 errors when guest agent isn't installed/running + diskStatusReason = "agent-not-running" + log.Info(). + Str("instance", instanceName). + Str("vm", vm.Name). + Int("vmid", vm.VMID). + Msg("Failed to communicate with guest agent (API error 500). This usually means qemu-guest-agent is not installed or not running in the VM") } else { diskStatusReason = "agent-error" }