Skip to content

[Bug] Upgrading from 5.28 → 6.1: cron store migrated to SQLite silently, but new jobs default to delivery.mode=announce causing channel errors #90378

@olveww-dot

Description

@olveww-dot

Summary

When upgrading OpenClaw from 2026.5.28 → 2026.6.1 via npm install -g openclaw@2026.6.1, the cron store migrated silently from JSON to SQLite without preserving the previous job config (or at least, the migration is not visible to the user). Additionally, the CLI default for new cron add jobs appears to be delivery: { mode: "announce", channel: "last" }, which fails because no delivery channel is configured in most installations.

This causes all cron jobs to fail with "Channel is required" on every run, even though the jobs themselves are well-formed.

Environment

  • OpenClaw version: 2026.6.1 (commit 2e08f0f)
  • Previous version: 2026.5.28
  • Host: macOS 15.4 (arm64), Node v24.14.1
  • Install path: /usr/local/lib/node_modules/openclaw
  • Cron store path: ~/.openclaw/cron/jobs.json (old) → ~/.openclaw/state/openclaw.sqlite (new)

Steps to Reproduce

  1. Start with OpenClaw 2026.5.28, with 12 cron jobs configured (all with delivery.mode: "none").
  2. Upgrade to 2026.6.1:
    npm install -g openclaw@2026.6.1
  3. Restart Gateway: launchctl kickstart -k gui/501/ai.openclaw.gateway
  4. Run: openclaw cron list

Expected: All 12 jobs are listed with their next-run times.

Actual: Only 1 job is listed (Memory Dreaming Promotion, which is a memory-core managed job that 6.1 itself added). The other 11 jobs are gone from the schedule, even though jobs.json.bak on disk still contains all 12 entries.

Investigation

Looking at the log file /tmp/openclaw/openclaw-2026-06-04.log:

22:13:40  cron: started  (jobs: 12)         ← still loading from JSON
22:26:05  cron: started  (jobs: 12)         ← post-upgrade, still 12
22:31:04  memory-core: created managed dreaming cron job.
22:31:04  cron: job added  Memory Dreaming  ← only this one added
22:31:04  cron: started  (jobs: 1)          ← now only 1!

It looks like 6.1's memory-core module overwrote the cron store when it registered the Memory Dreaming Promotion managed job. After that, all 12 original jobs were lost from the schedule, even though the JSON file on disk was not deleted (it was just no longer being read).

The cron store also moved from a flat JSON file to a SQLite database at ~/.openclaw/state/openclaw.sqlite — there is no visible migration path that brings the old jobs.json entries over.

Workaround (how I recovered)

  1. Manually read all 12 job definitions from jobs.json.bak (id, schedule, payload, delivery, etc.)
  2. Re-create each one via openclaw cron add with the same parameters.
  3. After each add, the default delivery was { mode: "announce", channel: "last" } — this is a separate bug because no channel is configured in this environment, so every cron run would fail with:
    Channel is required (no configured channels detected).
    
  4. Fix the delivery on each new job:
    openclaw cron update --jobId <id> --patch '{"delivery":{"mode":"none"}}'
  5. After this, openclaw cron list shows all 12 jobs and they are scheduled correctly.

Suggested Fixes

Issue A — silent cron store migration

The migration from jobs.json → SQLite should:

  1. Either auto-import the old JSON entries into the new SQLite store, or
  2. Print a clear warning during the upgrade (e.g. "Detected legacy jobs.json with 12 entries. Run openclaw cron migrate-legacy to import them."), or
  3. At minimum, leave the old jobs.json intact and document the manual recovery path in the changelog.

Issue B — default delivery.mode should be none, not announce

When openclaw cron add is called without --announce / --deliver, the resulting job's delivery defaults to { mode: "announce", channel: "last" }. For users who haven't configured a delivery channel (most users on a fresh install), this makes every cron run fail with a Channel is required error.

Suggested fix: default delivery.mode to "none" when no delivery flag is passed, OR detect at run time whether a channel is configured and skip the delivery silently instead of failing the whole job.

Issue C — failed delivery currently fails the whole cron run

Even when the actual payload (the agent turn) succeeds, a failure in the delivery layer currently marks the job run as error and triggers failure alerts. This is the wrong precedence — the work was done; only the announce step failed. The delivery failure should be logged but not bubble up as a job-level error.

Reproduction (minimal)

# fresh install
npm install -g openclaw@2026.6.1
openclaw gateway restart
openclaw cron add --cron "0 6 * * *" --tz "Asia/Shanghai" \
  --name "test-job" --session isolated \
  --model "minimax-portal/MiniMax-M2.7" \
  --message "hello"
# Wait until 06:00, or:
openclaw cron run <jobId>

# → Result: "Channel is required (no configured channels detected)"
#         lastStatus: "error"

The job's payload runs to completion in the log, but the cron run is marked failed purely because of the default delivery.

Real behavior proof (post-fix)

After patching each job with delivery.mode = "none", the next runs completed successfully:

22:14:30  cron: started  (jobs: 12, all enabled, all scheduled)
22:55:00  cron: job run  🧧 大乐透自动运营  → ok
23:00:00  cron: job run  📝 每日自动反思  → ok

The cron subsystem is now healthy and stable on my end.

Related

Thanks for the great project — happy to send a PR for any of the three fixes if the maintainer team is open to it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P0Emergency: data loss, security bypass, crash loop, or unusable core runtime.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:data-lossCan lose, corrupt, or silently drop user/session/config data.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions