troubleshooting openclaw cron scheduler api automation

Fix: OpenClaw Cron Jobs Created But Never Fire

Created a cron job in OpenClaw via the API but it never runs? It's probably missing nextRunAtMs. Here's why and how to fix it with the CLI instead.

Fix: OpenClaw Cron Jobs Created But Never Fire

TL;DR: Cron jobs created via the API are missing the nextRunAtMs field, so the scheduler never picks them up. Use the CLI to create cron jobs instead.

The Error

There's no error message — that's what makes this so frustrating. The cron job is created successfully:

# API call succeeds
curl -X POST http://localhost:3100/api/crons \
  -H "Content-Type: application/json" \
  -d '{
    "name": "daily-summary",
    "schedule": "0 9 * * *",
    "action": "send",
    "message": "Good morning! Here is your daily summary.",
    "channel": "telegram"
  }'

# Response: 200 OK, job created
{
  "id": "cron_abc123",
  "name": "daily-summary",
  "schedule": "0 9 * * *",
  "status": "active"
}

Everything looks fine. But 9am comes and goes. Nothing happens. The job just... never fires.

If you inspect the stored cron job, you'll notice:

{
  "id": "cron_abc123",
  "name": "daily-summary",
  "schedule": "0 9 * * *",
  "status": "active",
  "nextRunAtMs": null
}

nextRunAtMs is null. The scheduler checks this field to know when to run the job next. No value = no run.

Why This Happens

OpenClaw's cron scheduler uses nextRunAtMs (a Unix timestamp in milliseconds) to determine the next execution time. When you create a cron job through the CLI, it automatically calculates this value from the cron schedule and sets it. When you create one through the API, this calculation is skipped — the job is stored without a next-run timestamp.

The scheduler loop works like this:

every 60 seconds:
  for each cron job:
    if job.nextRunAtMs <= now:
      execute(job)
      job.nextRunAtMs = calculateNext(job.schedule)

If nextRunAtMs is null, the condition null <= now is false, so the job is silently skipped. Every time. Forever.

This is a bug in the API handler — it should calculate nextRunAtMs on creation, but it doesn't.

(GitHub #8207)

How to Fix It

Option A: Use the CLI instead of the API (recommended)

The CLI correctly sets nextRunAtMs:

# Create a cron job via CLI
openclaw cron create \
  --name "daily-summary" \
  --schedule "0 9 * * *" \
  --action send \
  --message "Good morning! Here's your daily summary." \
  --channel telegram

Verify it was created with a next-run time:

openclaw cron list

You should see:

NAME            SCHEDULE      NEXT RUN              STATUS
daily-summary   0 9 * * *     2026-02-04 09:00 UTC   active

Option B: Patch the nextRunAtMs manually

If you've already created jobs via the API and don't want to recreate them, you can set nextRunAtMs directly:

# Calculate the next run time (e.g., tomorrow at 9am UTC)
# Unix timestamp in milliseconds
NEXT_RUN=$(date -d "tomorrow 09:00:00 UTC" +%s%3N)

# Update the cron job via API
curl -X PATCH http://localhost:3100/api/crons/cron_abc123 \
  -H "Content-Type: application/json" \
  -d "{\"nextRunAtMs\": $NEXT_RUN}"

Or if you have the jq and node commands available, calculate it from the cron expression properly:

# Using node to calculate next cron occurrence
NEXT_RUN=$(node -e "
  const parser = require('cron-parser');
  const interval = parser.parseExpression('0 9 * * *');
  console.log(interval.next().getTime());
")

curl -X PATCH http://localhost:3100/api/crons/cron_abc123 \
  -H "Content-Type: application/json" \
  -d "{\"nextRunAtMs\": $NEXT_RUN}"

Option C: Fix it in the API source code

If you want to fix the root cause, find the cron creation handler in the OpenClaw source:

grep -r "cron.*create\|createCron\|POST.*cron" \
  ~/.config/openclaw/ /usr/lib/openclaw/ node_modules/openclaw/ 2>/dev/null

Look for the handler that creates cron jobs and add the nextRunAtMs calculation:

// After creating the cron job object, add:
const parser = require('cron-parser');
const interval = parser.parseExpression(cronJob.schedule);
cronJob.nextRunAtMs = interval.next().getTime();

Then restart:

openclaw gateway restart

Verify the fix

After creating or patching the cron job, wait for the scheduled time and check the logs:

# Watch for cron execution
openclaw logs --tail 100 --follow | grep -i cron

# Or check cron job status
openclaw cron list

How to Prevent It

  • Use the CLI for creating cron jobs until the API bug is fixed. The CLI has the correct initialization logic.
  • Always verify nextRunAtMs after creating a cron job. If it's null or missing, the job won't run.
  • Test with a short interval first. Before setting up a daily cron, create one that runs every 5 minutes (*/5 * * * *) to verify the scheduler is working:
openclaw cron create \
  --name "test-cron" \
  --schedule "*/5 * * * *" \
  --action send \
  --message "Cron test — if you see this, it's working" \
  --channel telegram

Delete it after confirming:

openclaw cron delete test-cron

The Easy Way

lobsterfarm is a managed hosting service for OpenClaw — deployment, updates, and support handled for you.

Get started with lobsterfarm →

Skip the setup. Start using your AI assistant today.

lobsterfarm gives you a fully managed OpenClaw instance — one click, your own server, running 24/7.