fix: bypass empty-heartbeat-file check for cron jobs#4256
Closed
radling005 wants to merge 2 commits intoopenclaw:mainfrom
Closed
fix: bypass empty-heartbeat-file check for cron jobs#4256radling005 wants to merge 2 commits intoopenclaw:mainfrom
radling005 wants to merge 2 commits intoopenclaw:mainfrom
Conversation
Cron jobs with wakeMode: 'now' were being skipped when HEARTBEAT.md was empty, even though they had pending system events to process. This adds cron jobs to the bypass list alongside exec events, since both have the same need: they've already enqueued system events and need the agent to wake up and process them. Fixes #4224
|
Thanks, thats what I had in mind too |
|
+1 |
radling005
pushed a commit
to radling005/openclaw
that referenced
this pull request
Feb 1, 2026
## Summary Two related fixes for cron job reliability: 1. **Empty HEARTBEAT.md bypass for cron jobs** (PR openclaw#4256 issue) - Cron jobs with `wakeMode: 'now'` were being skipped when HEARTBEAT.md was empty or contained only comments - Added `isCronReason` check alongside existing `isExecEventReason` bypass 2. **Prevent infinite retry loop for one-shot jobs** - Discovered while testing fix openclaw#1 - One-shot 'at' jobs that got skipped (e.g., quiet-hours) would immediately retry because `nextRunAtMs` remained set to the past time - Fix: Disable 'at' jobs after any attempt (ok, skipped, or error) ## Problem When a cron job fires with `wakeMode: 'now'`: 1. Enqueues system event via `enqueueSystemEvent()` 2. Calls `runHeartbeatOnce({ reason: 'cron:${job.id}' })` The heartbeat runner was checking if HEARTBEAT.md was empty and skipping, even though the cron job had already enqueued a system event to process. Additionally, for one-shot 'at' jobs that were skipped: - `computeJobNextRunAtMs()` returned the same past `atMs` time - Timer re-armed immediately, creating an infinite loop - Flood of cron events (1400+ per second observed) ## Testing - Verified cron job fires despite empty HEARTBEAT.md ✓ - Verified one-shot job disables after being skipped ✓ - All existing tests pass (cron: 52/52, heartbeat: 52/52) Fixes openclaw#4224
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Cron jobs with
wakeMode: 'now'were being skipped whenHEARTBEAT.mdwas empty or contained only comments, even though they had pending system events to process.Problem
When a cron job fires with
wakeMode: 'now', it:enqueueSystemEvent(text)runHeartbeatOnce({ reason: 'cron:${job.id}' })But
runHeartbeatOnce()checks ifHEARTBEAT.mdis effectively empty and skips if so — returning{ status: 'skipped', reason: 'empty-heartbeat-file' }.The bypass only existed for
reason === 'exec-event', not for cron jobs.Fix
Add cron jobs to the bypass list:
This ensures cron-triggered wakes are treated the same as exec-event wakes — both have pending system events that need processing regardless of
HEARTBEAT.mdstate.Testing
Tested locally with:
wakeMode: 'now'and emptyHEARTBEAT.mdlastStatus: 'skipped',lastError: 'empty-heartbeat-file'Fixes #4224