From 2dddfce08c2007c4560e9448351f2ba0115a8eec Mon Sep 17 00:00:00 2001 From: teknium1 Date: Tue, 10 Mar 2026 17:10:01 -0700 Subject: [PATCH] fix: log prefill parse errors + clean up cron scheduler tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to PR #716 (0xbyt4): - Log the third remaining silent except-pass in scheduler (prefill messages JSON parse failure) - Fix test mock: run → run_conversation (matches actual agent API) - Remove unused imports (asyncio, AsyncMock) - Add test for prefill_messages parse failure logging --- cron/scheduler.py | 3 ++- tests/cron/test_scheduler.py | 36 ++++++++++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/cron/scheduler.py b/cron/scheduler.py index 7675bbef..a8464cce 100644 --- a/cron/scheduler.py +++ b/cron/scheduler.py @@ -219,7 +219,8 @@ def run_job(job: dict) -> tuple[bool, str, str, Optional[str]]: prefill_messages = _json.load(_pf) if not isinstance(prefill_messages, list): prefill_messages = None - except Exception: + except Exception as e: + logger.warning("Job '%s': failed to parse prefill messages file '%s': %s", job_id, pfpath, e) prefill_messages = None # Max iterations diff --git a/tests/cron/test_scheduler.py b/tests/cron/test_scheduler.py index 6b817a28..824af11f 100644 --- a/tests/cron/test_scheduler.py +++ b/tests/cron/test_scheduler.py @@ -1,8 +1,8 @@ """Tests for cron/scheduler.py — origin resolution, delivery routing, and error logging.""" -import asyncio +import json import logging -from unittest.mock import patch, MagicMock, AsyncMock +from unittest.mock import patch, MagicMock import pytest @@ -74,7 +74,6 @@ class TestRunJobConfigLogging: def test_bad_config_yaml_is_logged(self, caplog, tmp_path): """When config.yaml is malformed, a warning should be logged.""" - # Create a bad config.yaml bad_yaml = tmp_path / "config.yaml" bad_yaml.write_text("invalid: yaml: [[[bad") @@ -89,7 +88,7 @@ class TestRunJobConfigLogging: patch("dotenv.load_dotenv"), \ patch("run_agent.AIAgent") as mock_agent_cls: mock_agent = MagicMock() - mock_agent.run.return_value = ("output doc", "final response") + mock_agent.run_conversation.return_value = {"final_response": "ok"} mock_agent_cls.return_value = mock_agent with caplog.at_level(logging.WARNING, logger="cron.scheduler"): @@ -97,3 +96,32 @@ class TestRunJobConfigLogging: assert any("failed to load config.yaml" in r.message for r in caplog.records), \ f"Expected 'failed to load config.yaml' warning in logs, got: {[r.message for r in caplog.records]}" + + def test_bad_prefill_messages_is_logged(self, caplog, tmp_path): + """When the prefill messages file contains invalid JSON, a warning should be logged.""" + # Valid config.yaml that points to a bad prefill file + config_yaml = tmp_path / "config.yaml" + config_yaml.write_text("prefill_messages_file: prefill.json\n") + + bad_prefill = tmp_path / "prefill.json" + bad_prefill.write_text("{not valid json!!!") + + job = { + "id": "test-job", + "name": "test", + "prompt": "hello", + } + + with patch("cron.scheduler._hermes_home", tmp_path), \ + patch("cron.scheduler._resolve_origin", return_value=None), \ + patch("dotenv.load_dotenv"), \ + patch("run_agent.AIAgent") as mock_agent_cls: + mock_agent = MagicMock() + mock_agent.run_conversation.return_value = {"final_response": "ok"} + mock_agent_cls.return_value = mock_agent + + with caplog.at_level(logging.WARNING, logger="cron.scheduler"): + run_job(job) + + assert any("failed to parse prefill messages" in r.message for r in caplog.records), \ + f"Expected 'failed to parse prefill messages' warning in logs, got: {[r.message for r in caplog.records]}"