Bug type
Regression / migration bug
Summary
Legacy cron jobs that still store:
schedule as a plain cron string
- top-level
command / timeout
are not fully migrated when the cron store loads.
The loader only infers payloads from top-level message and text, and it expects schedule to already be an object. As a result, old jobs can hit schedule parsing failures on startup and end up skipped or auto-disabled instead of being normalized.
Steps to reproduce
- Put a legacy job entry in
~/.openclaw/cron/jobs.json, for example:
{
"id": "imessage-refresh",
"name": "iMessage Refresh",
"enabled": true,
"createdAtMs": 1700000000000,
"updatedAtMs": 1700000000000,
"schedule": "0 */2 * * *",
"command": "bash /tmp/imessage-refresh.sh",
"timeout": 120,
"state": {}
}
- Start the gateway / cron service.
- Inspect the loaded store and cron logs.
Expected behavior
The loader should migrate the legacy entry to the current shape:
schedule: { kind: "cron", expr: ... }
payload: { kind: "systemEvent", text: command }
- remove obsolete top-level
command and timeout
- infer the correct
sessionTarget
Actual behavior
The legacy fields are left behind, the payload is not inferred from command, and the schedule string is not normalized before the scheduler evaluates it. That can leave the job skipped or auto-disabled with schedule errors instead of being migrated cleanly.
OpenClaw version
main
Operating system
cross-platform
Install method
source build / local checkout
Logs, screenshots, and evidence
Current loader code in src/cron/service/store.ts only infers payloads from top-level message / text and does not normalize string schedule values before recomputing runs.
Related historical report: closed issue #18445 described the same legacy store shape and failure mode, but the current migration path still misses that case.
Impact and severity
Medium. This affects upgrades from older cron store formats and can silently degrade scheduled jobs after startup.
Additional information
A focused migration fix can solve this without changing current cron job formats or runtime behavior for already-valid jobs.
Bug type
Regression / migration bug
Summary
Legacy cron jobs that still store:
scheduleas a plain cron stringcommand/timeoutare not fully migrated when the cron store loads.
The loader only infers payloads from top-level
messageandtext, and it expectsscheduleto already be an object. As a result, old jobs can hit schedule parsing failures on startup and end up skipped or auto-disabled instead of being normalized.Steps to reproduce
~/.openclaw/cron/jobs.json, for example:{ "id": "imessage-refresh", "name": "iMessage Refresh", "enabled": true, "createdAtMs": 1700000000000, "updatedAtMs": 1700000000000, "schedule": "0 */2 * * *", "command": "bash /tmp/imessage-refresh.sh", "timeout": 120, "state": {} }Expected behavior
The loader should migrate the legacy entry to the current shape:
schedule: { kind: "cron", expr: ... }payload: { kind: "systemEvent", text: command }commandandtimeoutsessionTargetActual behavior
The legacy fields are left behind, the payload is not inferred from
command, and the schedule string is not normalized before the scheduler evaluates it. That can leave the job skipped or auto-disabled with schedule errors instead of being migrated cleanly.OpenClaw version
main
Operating system
cross-platform
Install method
source build / local checkout
Logs, screenshots, and evidence
Current loader code in
src/cron/service/store.tsonly infers payloads from top-levelmessage/textand does not normalize stringschedulevalues before recomputing runs.Related historical report: closed issue #18445 described the same legacy store shape and failure mode, but the current migration path still misses that case.
Impact and severity
Medium. This affects upgrades from older cron store formats and can silently degrade scheduled jobs after startup.
Additional information
A focused migration fix can solve this without changing current cron job formats or runtime behavior for already-valid jobs.