Description
openclaw cron run <job-id> returns { "ok": true, "enqueued": true } but the job never actually executes. The cron scheduler timer wakes every 60 seconds but only checks nextAt for scheduled jobs — it never processes the manual run queue.
Version
OpenClaw 2026.3.8 (3caab92) — macOS 26.3.1 (arm64), Node v25.5.0
Steps to Reproduce
- Have a cron job configured (e.g. a daily morning briefing)
- Run
openclaw cron run <job-id>
- Observe
{ "ok": true, "enqueued": true, "runId": "manual:..." } response
- Wait — the job never executes
Evidence from Logs
The cron module timer keeps arming for the next scheduled time and never picks up the manual queue:
09:41:12 { "ok": true, "enqueued": true, "runId": "manual:402eb51d-...:1" }
09:42:04 cron: timer armed → nextAt 10:00
09:43:04 cron: timer armed → nextAt 10:00
09:44:04 cron: timer armed → nextAt 10:00
... (repeats every 60s, manual run never starts)
No new entries appear in openclaw cron runs --id <job-id> — only the previous scheduled run.
Secondary Issue: Stale runningAtMs Lock
When cron run enqueues a job, it appears to set runningAtMs in jobs.json state even though the run never starts. This leaves a stale lock that blocks future scheduled and manual runs for that job.
State in jobs.json after failed manual trigger:
{
"nextRunAtMs": 1773820800000,
"lastRunAtMs": 1773216000015,
"lastStatus": "error",
"runningAtMs": 1773218472820 // <-- stale, never cleared
}
Workaround: Manually delete runningAtMs from the job state in ~/.openclaw/cron/jobs.json.
Context
This was discovered after an internet outage caused scheduled cron jobs to fail with LLM timeouts. Attempted to re-trigger them manually via cron run but they never executed. Had to work around by spawning sub-agents directly with sessions_spawn.
Expected Behavior
openclaw cron run <job-id> should immediately execute the job (or at least execute within the next scheduler tick). The runningAtMs flag should not be set until the job actually starts executing.
Description
openclaw cron run <job-id>returns{ "ok": true, "enqueued": true }but the job never actually executes. The cron scheduler timer wakes every 60 seconds but only checksnextAtfor scheduled jobs — it never processes the manual run queue.Version
OpenClaw 2026.3.8 (3caab92) — macOS 26.3.1 (arm64), Node v25.5.0
Steps to Reproduce
openclaw cron run <job-id>{ "ok": true, "enqueued": true, "runId": "manual:..." }responseEvidence from Logs
The cron module timer keeps arming for the next scheduled time and never picks up the manual queue:
No new entries appear in
openclaw cron runs --id <job-id>— only the previous scheduled run.Secondary Issue: Stale
runningAtMsLockWhen
cron runenqueues a job, it appears to setrunningAtMsinjobs.jsonstate even though the run never starts. This leaves a stale lock that blocks future scheduled and manual runs for that job.State in jobs.json after failed manual trigger:
{ "nextRunAtMs": 1773820800000, "lastRunAtMs": 1773216000015, "lastStatus": "error", "runningAtMs": 1773218472820 // <-- stale, never cleared }Workaround: Manually delete
runningAtMsfrom the job state in~/.openclaw/cron/jobs.json.Context
This was discovered after an internet outage caused scheduled cron jobs to fail with LLM timeouts. Attempted to re-trigger them manually via
cron runbut they never executed. Had to work around by spawning sub-agents directly withsessions_spawn.Expected Behavior
openclaw cron run <job-id>should immediately execute the job (or at least execute within the next scheduler tick). TherunningAtMsflag should not be set until the job actually starts executing.