#Cron jobs scheduled but not executing (both cron expressions and one‑shot at jobs)

1 messages · Page 1 of 1 (latest)

lilac kettle
#

...Problem: Gateway's internal cron scheduler accepts and stores jobs but fails to execute them at scheduled times. Jobs show correct nextRunAtMs timestamps but never fire.

Evidence:

  1. Recurring cron jobs never executed: • Morning Brief (created Feb 7, schedule 0 23 * * * UTC) → never ran
    • Alfred Email Monitor (created Feb 7, 0 0 * * * UTC) → never ran
    • Evening Recap (created Feb 7, 0 12 * * * UTC) → scheduled for tonight, no prior runs

  2. One‑shot at jobs also fail: • Created 9:30 AM GMT+8 news update (fd112935‑…, at: 2026‑02‑08T01:30:00Z)
    • Job shows nextRunAtMs: 1770514200000 (correct)
    • No run file created in ~/.openclaw/cron/runs/
    • No output delivered

  3. Last successful cron execution: Feb 5, 2026 (Daily Competitive Brief) • All subsequent jobs remain in jobs.json with future nextRunAtMs but never trigger

Steps to reproduce:

  1. Create a one‑shot job via openclaw cron add --at "2026‑02‑08T01:30:00Z" --session isolated --message "test" --announce
  2. Verify job appears in cron list with correct nextRunAtMs
  3. Wait for scheduled time
  4. Expected: Job executes, creates run file, delivers output
  5. Actual: Job silent, no run file, no output
    Environment:

• OpenClaw: 2026.2.3‑1 (d84eb46)
• OS: Ubuntu 24.04 LTS (Linux 6.8.0‑94‑generic)
• Gateway: Running since Feb 6 (PID 1186885)
• Config: cron.enabled: true, store path default
Workarounds attempted:

  1. Gateway restart → jobs recalculated but still not executing

  2. One‑shot jobs → same failure as cron expressions

  3. Manual cron wake → triggers heartbeat but not job execution

  4. Created system cron wrappers (7 scripts using openclaw agent/message) as fallback
    Questions:

  5. Is there a known issue with the cron scheduler's timer/wake mechanism?

  6. How can we debug why jobs with valid nextRunAtMs aren't firing?

  7. Are there logs (gateway/cron) that would show scheduler activity?

  8. Could this be related to timezone handling (UTC vs GMT+8)?

woven tuskBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> ✅ Mark Solution

night tigerBOT
# lilac kettle ...Problem: Gateway's internal cron scheduler accepts and stores jobs but fails ...

A few concrete things to check here — cron scheduling is very simple internally (it’s just a setTimeout inside the Gateway), so when it “never fires”, it’s usually one of: cron is actually disabled, the Gateway you’re looking at isn’t the one running, or the Gateway is pointed at a different cron store path/state dir.

1) First sanity check: what does the running Gateway think?

Run these on the gateway host and paste the outputs:

openclaw gateway status
openclaw cron status --json
openclaw cron list --json

In particular, openclaw cron status --json should show something like:

  • enabled: true
  • storePath: /home/<user>/.openclaw/cron/jobs.json (or wherever you expect)
  • jobs: <n>
  • nextWakeAtMs: <timestamp> (should be near the next job time; if it’s null, the timer will never arm)
#

If enabled is false, the two most common causes are:

  • OPENCLAW_SKIP_CRON=1 in the service environment (easy to miss if you set it once while debugging)
  • the gateway service is running a different config/profile than your CLI edits (see FAQ entry about “Config (cli) vs Config (service) different”)

2) “cron wake” doesn’t run jobs (common confusion)

openclaw cron wake … just injects a system event / nudges heartbeat. It won’t “kick” due jobs.

To prove the execution pipeline works independently of scheduling, try:

openclaw cron run <jobId> --force
openclaw cron runs --id <jobId> --limit 50
  • If cron run --force works but scheduled runs don’t → timer/arming/enablement issue.
  • If cron run --force also does nothing / errors → execution path or gateway health issue (logs will matter).
#

3) Logs to look at (this should show something)

Tail logs and filter for cron:

openclaw logs --follow --plain | rg -i "cron"

At gateway startup you should see a line like cron: started (or cron: disabled / “scheduler disabled; jobs will not run automatically”).

If you never see cron: started on boot, that’s a strong signal cron is disabled via env/config mismatch.

Docs refs:

4) Timezone: unlikely to explain the one-shot failure

#
  • For --at "…Z" jobs, timezone is irrelevant (absolute UTC).
  • For --cron "…" jobs, timezone matters only if you omit --tz (then it uses the gateway host timezone). So I’d still recommend always setting --tz UTC (or your desired IANA TZ), but it wouldn’t explain “never fires” for --at.

If the above shows enabled:true, correct storePath, and a sensible nextWakeAtMs, but nothing ever runs

That’s bug territory. Best next step is to file a GitHub issue with:

  • openclaw cron status --json
  • openclaw gateway status
  • a short openclaw logs --follow snippet covering gateway startup + when a job should have fired

Issues: https://github.com/openclaw/openclaw/issues

If you paste openclaw cron status --json here, I can tell you immediately whether this is “cron disabled / wrong storePath” vs “timer armed but not ticking”.

lilac kettle
#
  1. openclaw gateway status:
    Service: systemd (enabled)
    Config (cli): ~/.openclaw/openclaw.json
    Config (service): ~/.openclaw/openclaw.json
    Runtime: running (pid 1186885, state active)
    RPC probe: ok
  2. openclaw cron status --json:
    {
    "enabled": true,
    "storePath": "/home/ubuntu/.openclaw/cron/jobs.json",
    "jobs": 10,
    "nextWakeAtMs": null
    }
  3. Logs (openclaw logs | grep cron):
    2026-02-08T00:24:24 info cron: started
    {"enabled":true,"jobs":9,"nextWakeAtMs":1770552000000}
  4. Key Finding:

• One-shot at jobs WORK ✅ (tested 9:30 AM and 10:00 AM — both fired successfully, run files created, output delivered)
• Recurring cron expressions DON'T WORK ❌ (Morning Brief 0 23 * * *, Email Monitor 0 0 * * *, Evening Recap 0 12 * * * — never executed since Feb 5)
Conclusion: Scheduler is enabled, timer arms correctly for one-shot at jobs, but recurring cron expressions never fire. Bug appears specific to cron expression scheduling.

night tigerBOT
# lilac kettle 1. openclaw gateway status: Service: systemd (enabled) Config (cli): ~/.openclaw...

That nextWakeAtMs: null is the smoking gun.

Cron only “ticks” if it can compute a next wake time from at least one enabled job’s state.nextRunAtMs. If nextWakeAtMs is null, the gateway won’t arm the scheduler timer → nothing recurring will ever fire.

So the question becomes: why do none of the 10 jobs currently contribute a valid nextRunAtMs?

1) Please paste one “broken” job (JSON) + a quick table

Run:

openclaw cron list --all --json | jq -r '
.[] | [
  .id,
  .enabled,
  .schedule.kind,
  (.schedule.expr // .schedule.at // ""),
#
  (.schedule.tz // ""),
  (.state.nextRunAtMs // "")
] | @tsv'

This will immediately reveal one of these cases:

  • All jobs are enabled=false → cron status will show nextWakeAtMs: null.

    • Fix: openclaw cron enable <id> for the recurring ones.
  • Jobs are enabled but their schedule is malformed so next run can’t be computed (often expr is empty, or not what you think).

2) Common “cron expr” gotcha: timezone accidentally embedded in the expression

You wrote schedules like 0 23 * * * UTC in the report.

OpenClaw’s cron expression must be 5 fields. Timezone is a separate field (--tz / schedule.tz).

#

Correct:

--cron "0 23 * * *" --tz "UTC"

Wrong (breaks scheduling):

--cron "0 23 * * * UTC"

So in the JSON above, check whether .schedule.expr literally contains UTC as an extra token. If yes, re-create/edit those jobs with --tz UTC and a 5-field expr.

3) Quick “does cron expr work at all on this gateway?” smoke test (no delivery spam)

Create a brand-new recurring job that runs every 2 minutes, but keeps output internal:

#
openclaw cron add \
  --name "cron expr smoke" \
  --cron "*/2 * * * *" \
  --tz UTC \
  --session isolated \
  --message "cron smoke tick" \
  --no-deliver

Then:

openclaw cron status --json

If nextWakeAtMs becomes non-null after this, the scheduler is fine and your existing recurring jobs are likely disabled or have malformed schedules.