{"record":{"id":"6a49636508eaa2a5","repo":"HKUDS/Vibe-Trading","slug":"retry-base-delay-ms-must-be-non-negative","errorCode":null,"errorMessage":"retry_base_delay_ms must be non-negative","messagePattern":"retry_base_delay_ms must be non-negative","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/scheduled_research/executor.py","lineNumber":269,"sourceCode":"        self._max_consecutive_failures = (\n            max_consecutive_failures\n            if max_consecutive_failures is not None\n            else tuning.vibe_trading_scheduler_max_consecutive_failures\n        )\n        self._retry_base_delay_ms = (\n            retry_base_delay_ms\n            if retry_base_delay_ms is not None\n            else tuning.vibe_trading_scheduler_retry_base_delay_ms\n        )\n        self._retry_max_delay_ms = (\n            retry_max_delay_ms\n            if retry_max_delay_ms is not None\n            else tuning.vibe_trading_scheduler_retry_max_delay_ms\n        )\n        if self._max_consecutive_failures < 1:\n            raise ValueError(\"max_consecutive_failures must be at least 1\")\n        if self._retry_base_delay_ms < 0:\n            raise ValueError(\"retry_base_delay_ms must be non-negative\")\n        if self._retry_max_delay_ms < self._retry_base_delay_ms:\n            raise ValueError(\"retry_max_delay_ms must be at least retry_base_delay_ms\")\n        self._task: asyncio.Task | None = None\n        self._wakeup: asyncio.Event | None = None\n        self._stopping = False\n        self._recovered_stale_running = False\n\n    @property\n    def is_running(self) -> bool:\n        \"\"\"Return whether the background loop task is active.\"\"\"\n        return self._task is not None and not self._task.done()\n\n    def start(self) -> None:\n        \"\"\"Start the background loop.\n\n        Idempotent. When disabled, this is a no-op.\n        \"\"\"\n        if not self._enabled or self.is_running:","sourceCodeStart":251,"sourceCodeEnd":287,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/scheduled_research/executor.py#L251-L287","documentation":"The executor's exponential-backoff retry uses retry_base_delay_ms as the initial sleep between retries, so it must be non-negative. Negative delays are meaningless as timers and would be rejected by asyncio.sleep anyway, so the constructor fails fast.","triggerScenarios":"Constructing the executor with retry_base_delay_ms=-1000 or a negative tuning value (e.g. a mis-parsed env var or a subtraction bug in config code).","commonSituations":"Typo'd config numbers, unit conversions producing negatives, or settings templates where -1 is used as a sentinel for 'unset' and passed through without translation.","solutions":["Set retry_base_delay_ms to 0 (immediate first retry) or a positive millisecond value such as 1000.","Translate sentinel values like -1 to None/defaults before constructing the executor.","Audit the tuning object feeding the parameter."],"exampleFix":"# before\nSchedulerExecutor(retry_base_delay_ms=-1)\n# after\nSchedulerExecutor(retry_base_delay_ms=1000)","handlingStrategy":"validation","validationCode":"retry_base_delay_ms = max(0, int(retry_base_delay_ms))\nexecutor = SchedulerExecutor(retry_base_delay_ms=retry_base_delay_ms)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Map config sentinels like -1 to the default, not into the constructor.","Unit-test config parsing for negative numbers."],"tags":["python","scheduler","config-validation","retry"],"backgroundTag":"invalid-configuration-value","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}