From d9b20c0cf6b583210412757f8465d38de4100b49 Mon Sep 17 00:00:00 2001 From: JackChen Date: Fri, 3 Apr 2026 14:14:34 +0800 Subject: [PATCH] fix: guard retry fields against Infinity/NaN Use Number.isFinite() to sanitize maxRetries, retryDelayMs, and retryBackoff before entering the retry loop. Prevents unbounded retries from Infinity or broken loop bounds from NaN. --- src/orchestrator/orchestrator.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/orchestrator/orchestrator.ts b/src/orchestrator/orchestrator.ts index 9d6d857..848bfde 100644 --- a/src/orchestrator/orchestrator.ts +++ b/src/orchestrator/orchestrator.ts @@ -128,9 +128,10 @@ export async function executeWithRetry( onRetry?: (data: { attempt: number; maxAttempts: number; error: string; nextDelayMs: number }) => void, delayFn: (ms: number) => Promise = sleep, ): Promise { - const maxAttempts = Math.max(0, task.maxRetries ?? 0) + 1 - const baseDelay = Math.max(0, task.retryDelayMs ?? 1000) - const backoff = Math.max(1, task.retryBackoff ?? 2) + const rawRetries = Number.isFinite(task.maxRetries) ? task.maxRetries! : 0 + const maxAttempts = Math.max(0, rawRetries) + 1 + const baseDelay = Math.max(0, Number.isFinite(task.retryDelayMs) ? task.retryDelayMs! : 1000) + const backoff = Math.max(1, Number.isFinite(task.retryBackoff) ? task.retryBackoff! : 2) let lastError: string = '' // Accumulate token usage across all attempts so billing/observability