From d0969ad57a2e013ea95e758348445c872d438e0a Mon Sep 17 00:00:00 2001 From: Chuck Date: Tue, 28 Apr 2026 09:29:08 -0400 Subject: [PATCH] fix(plugin_manager): prevent permanent ERROR state after update timeout When execute_update() fails (timeout or unhandled exception), the plugin state was set to ERROR with no recovery path. can_execute() returns False for ERROR state, so the plugin's update() was never called again, leaving it showing stale data indefinitely. Instead, update plugin_last_update so the plugin waits one configured interval before retrying, and keep the state ENABLED so recovery is automatic on the next cycle. Co-Authored-By: Claude Sonnet 4.6 --- src/plugin_system/plugin_manager.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/plugin_system/plugin_manager.py b/src/plugin_system/plugin_manager.py index d6cc7139..64b31dcf 100644 --- a/src/plugin_system/plugin_manager.py +++ b/src/plugin_system/plugin_manager.py @@ -734,14 +734,18 @@ class PluginManager: if self.health_tracker: self.health_tracker.record_success(plugin_id) else: - # Execution failed (timeout or error) - self.state_manager.set_state(plugin_id, PluginState.ERROR) + # Execution failed (timeout or error) — update timestamp so the + # plugin waits one full interval before retrying, but keep state + # ENABLED so can_execute() returns True and recovery is automatic. + self.plugin_last_update[plugin_id] = current_time + self.state_manager.set_state(plugin_id, PluginState.ENABLED) if self.health_tracker: self.health_tracker.record_failure(plugin_id, Exception("Plugin execution failed")) except Exception as exc: # pylint: disable=broad-except self.logger.exception("Error updating plugin %s: %s", plugin_id, exc) - self.state_manager.set_state(plugin_id, PluginState.ERROR, error=exc) - # Record failure + # Same as the failure path above: stay ENABLED and wait one interval. + self.plugin_last_update[plugin_id] = current_time + self.state_manager.set_state(plugin_id, PluginState.ENABLED) if self.health_tracker: self.health_tracker.record_failure(plugin_id, exc)