fix(scheduler): fall back to defaults for non-numeric research settings

The scheduled-research task reads research_max_tokens,
research_extraction_timeout_seconds, and research_extraction_concurrency
with bare int() casts and no guard. A hand-edited or agent-written
data/settings.json value like {"research_max_tokens": "invalid"} raised
ValueError and killed every scheduled research run until settings.json was
fixed by hand (#5049). src/research_handler.py already guards the same reads
defensively (_bounded_int); this mirrors that for the scheduler.

Wrap the three reads in try/except (TypeError, ValueError) falling back to
the documented defaults 8192 / 90 / 3. Valid values (numeric strings like
"4096") still parse; the change is limited to the scheduler's reads (agent_loop
sites are tracked separately in #5051).

Child of maintainer subtracker #5335 (RaresKeY) whose acceptance criteria state:
"Non-numeric agent/scheduler settings fall back safely instead of crashing or
silently degrading." Prior PR #5050 attempted the same fix but was closed
unmerged in the 2026-07-23 repo-transfer bulk close and never resubmitted —
redoing it with credit.

Fixes #5049.
This commit is contained in:
ShahabAhmed01
2026-10-03 23:23:36 +05:00
parent 2992bf6d36
commit 35e3b298d8
2 changed files with 112 additions and 3 deletions
+33 -3
View File
@@ -342,6 +342,36 @@ def _normalize_chat_endpoint(url: str) -> str:
return url
def _resolve_research_settings(get_setting_fn):
"""Resolve the scheduled-research settings with crash-proof fallbacks.
A hand-edited or agent-written data/settings.json can hold non-numeric
values for the research_* keys; the bare int() reads previously raised
inside TaskScheduler._execute_research_task and killed every scheduled
research run until settings.json was fixed by hand (#5049).
src/research_handler.py already guards the same reads defensively —
this mirrors that for the scheduler. Valid values pass through
unchanged (numeric strings like "4096" still parse).
"""
try:
max_tokens = int(get_setting_fn("research_max_tokens", 8192))
except (TypeError, ValueError):
max_tokens = 8192
try:
extraction_timeout = int(
get_setting_fn("research_extraction_timeout_seconds", 90) or 90
)
except (TypeError, ValueError):
extraction_timeout = 90
try:
extraction_concurrency = int(
get_setting_fn("research_extraction_concurrency", 3) or 3
)
except (TypeError, ValueError):
extraction_concurrency = 3
return max_tokens, extraction_timeout, extraction_concurrency
class TaskScheduler:
def __init__(self, session_manager):
self._session_manager = session_manager
@@ -2068,9 +2098,9 @@ class TaskScheduler:
except Exception:
pass
max_tokens = int(get_setting("research_max_tokens", 8192))
extraction_timeout = int(get_setting("research_extraction_timeout_seconds", 90) or 90)
extraction_concurrency = int(get_setting("research_extraction_concurrency", 3) or 3)
max_tokens, extraction_timeout, extraction_concurrency = (
_resolve_research_settings(get_setting)
)
researcher = DeepResearcher(
llm_endpoint=endpoint_url,