-
-
Notifications
You must be signed in to change notification settings - Fork 39.8k
Description
Problem
Cron jobs with wakeMode: "now" and payload.kind: "systemEvent" fail to deliver when HEARTBEAT.md exists but is effectively empty (only comments/headers). The job state shows:
"lastError": "empty-heartbeat-file",
"lastStatus": "skipped"Expected behavior
wakeMode: "now" should force immediate delivery regardless of HEARTBEAT.md state. The empty-file optimization makes sense for periodic heartbeats, but not for explicit wake requests.
Root cause
In src/infra/heartbeat-runner.ts:463-468, the empty-file check only bypasses for reason === "exec-event":
const isExecEventReason = opts.reason === "exec-event";
// ...
if (isHeartbeatContentEffectivelyEmpty(heartbeatFileContent) && !isExecEventReason) {
return { status: "skipped", reason: "empty-heartbeat-file" };
}When a cron job with wakeMode: "now" runs (src/cron/service/timer.ts:153-161), it:
- Calls
enqueueSystemEvent(text, ...)at line 152 - Calls
runHeartbeatOnce({ reason: "cron:${job.id}" })at line 161
The reason "cron:abc123" doesn't match "exec-event", so the bypass doesn't trigger - even though the job has pending system events to process (just like exec events do).
Related issues
| Issue | Status | Symptom | Resolution |
|---|---|---|---|
| #652 | CLOSED | durationMs: 0, no agent processing |
Fixed via PR #666 |
| #2217 | CLOSED | empty-heartbeat-file skip |
Closed as inactive (not fixed) |
| #2302 | CLOSED | No WhatsApp delivery | Duplicate of #2217 |
| #2549 | CLOSED | empty-heartbeat-file skip |
Duplicate of #2217 |
| #2937 | OPEN | Messages reach agent but not Telegram | Separate delivery bug |
| #3887 | CLOSED | Status "ok" but silent delivery failure | Duplicate of #2937 |
| #4098 | OPEN | empty-heartbeat-file + jobs persist |
Most comprehensive report |
Note: #2217 was closed as "inactive" but the bug was never fixed. #4098 is the most recent and comprehensive report of this issue. #2937 appears to be a separate channel delivery bug.