From ec0a1d77972279c172969036ffd4c2fdd3cea974 Mon Sep 17 00:00:00 2001 From: HollyChou <128659251+Hollychou924@users.noreply.github.com> Date: Fri, 20 Mar 2026 08:46:00 +0800 Subject: [PATCH] fix(cron): use agent-turn safety timeout for systemEvent jobs with wakeMode=now When a cron job has sessionTarget="main", payload.kind="systemEvent", and wakeMode="now", executeJobCore() calls runHeartbeatOnce() which blocks until the full agent turn completes. The turn duration is unbounded (multi-step tasks may take 30+ minutes), but resolveCronJobTimeoutMs() was returning DEFAULT_JOB_TIMEOUT_MS (10 minutes) for all systemEvent jobs, causing spurious "cron: job execution timed out" errors. Fix: when wakeMode="now" + sessionTarget="main" + kind="systemEvent", return AGENT_TURN_SAFETY_TIMEOUT_MS (60 minutes) instead of the short 10-minute default. Fixes #50621 --- src/cron/service/timeout-policy.ts | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/cron/service/timeout-policy.ts b/src/cron/service/timeout-policy.ts index 7b03b8bda52..607a8fa8921 100644 --- a/src/cron/service/timeout-policy.ts +++ b/src/cron/service/timeout-policy.ts @@ -19,7 +19,25 @@ export function resolveCronJobTimeoutMs(job: CronJob): number | undefined { ? Math.floor(job.payload.timeoutSeconds * 1_000) : undefined; if (configuredTimeoutMs === undefined) { - return job.payload.kind === "agentTurn" ? AGENT_TURN_SAFETY_TIMEOUT_MS : DEFAULT_JOB_TIMEOUT_MS; + // agentTurn jobs get the large safety ceiling since turns can run for a long time. + if (job.payload.kind === "agentTurn") { + return AGENT_TURN_SAFETY_TIMEOUT_MS; + } + // systemEvent jobs targeting "main" with wakeMode="now" call runHeartbeatOnce(), + // which blocks until the full agent turn completes. The turn duration is + // unbounded, so apply the same generous ceiling as agentTurn jobs instead of + // the short DEFAULT_JOB_TIMEOUT_MS that was incorrectly timing out long-running + // main-session heartbeats. See: https://github.com/openclaw/openclaw/issues/50621 + if ( + job.payload.kind === "systemEvent" && + job.sessionTarget === "main" && + job.wakeMode === "now" + ) { + return AGENT_TURN_SAFETY_TIMEOUT_MS; + } + // All other systemEvent jobs (wakeMode !== "now") are fire-and-forget: + // they enqueue the event and return immediately, so the short default is fine. + return DEFAULT_JOB_TIMEOUT_MS; } return configuredTimeoutMs <= 0 ? undefined : configuredTimeoutMs; }