From c2a7921f3bc8f96f3cd07c8777dc901655005cf9 Mon Sep 17 00:00:00 2001 From: Eris Date: Wed, 11 Mar 2026 16:00:25 +0800 Subject: [PATCH] fix: prevent logging handler accumulation in gateway mode Use exact Path comparison instead of endswith to detect existing errors.log handlers, avoiding false positives from similarly-named log files. --- run_agent.py | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/run_agent.py b/run_agent.py index b9bacf7d..9b30d4f0 100644 --- a/run_agent.py +++ b/run_agent.py @@ -407,19 +407,30 @@ class AIAgent: # Persistent error log -- always writes WARNING+ to ~/.hermes/logs/errors.log # so tool failures, API errors, etc. are inspectable after the fact. - from agent.redact import RedactingFormatter - _error_log_dir = _hermes_home / "logs" - _error_log_dir.mkdir(parents=True, exist_ok=True) - _error_log_path = _error_log_dir / "errors.log" + # In gateway mode, each incoming message creates a new AIAgent instance, + # while the root logger is process-global. Re-adding the same errors.log + # handler would cause each warning/error line to be written multiple times. from logging.handlers import RotatingFileHandler - _error_file_handler = RotatingFileHandler( - _error_log_path, maxBytes=2 * 1024 * 1024, backupCount=2, + root_logger = logging.getLogger() + error_log_dir = _hermes_home / "logs" + error_log_path = error_log_dir / "errors.log" + resolved_error_log_path = error_log_path.resolve() + has_errors_log_handler = any( + isinstance(handler, RotatingFileHandler) + and Path(getattr(handler, "baseFilename", "")).resolve() == resolved_error_log_path + for handler in root_logger.handlers ) - _error_file_handler.setLevel(logging.WARNING) - _error_file_handler.setFormatter(RedactingFormatter( - '%(asctime)s %(levelname)s %(name)s: %(message)s', - )) - logging.getLogger().addHandler(_error_file_handler) + if not has_errors_log_handler: + from agent.redact import RedactingFormatter + error_log_dir.mkdir(parents=True, exist_ok=True) + error_file_handler = RotatingFileHandler( + error_log_path, maxBytes=2 * 1024 * 1024, backupCount=2, + ) + error_file_handler.setLevel(logging.WARNING) + error_file_handler.setFormatter(RedactingFormatter( + '%(asctime)s %(levelname)s %(name)s: %(message)s', + )) + root_logger.addHandler(error_file_handler) if self.verbose_logging: logging.basicConfig(