Cron Scheduler TypeError: Cannot read properties of undefined (reading 'runningAtMs')
The OpenClaw cron scheduler crashes during startup catchup due to job objects being replaced with state-deficient versions, causing CLI WebSocket calls to hang.
🔍 Symptom
A TypeError is thrown when the cron scheduler attempts to access the runningAtMs property on an undefined object.
Error Stack Trace:
cron.start()runMissedJobs()planStartupCatchup()
Additional Symptoms:
- CLI commands (
openclaw cron add,openclaw cron list) become unresponsive - WebSocket handshake hangs indefinitely after gateway restart
- Gateway repeatedly crashes and restarts in a loop
- HTTP API calls for cron status may also fail
Version Affected: OpenClaw 2026.4.9 (Docker 4.10)
Version Known Working: OpenClaw 3.29
🧠 Principle
Root Cause: A race condition in the cron startup sequence causes job objects stored in memory to be replaced with incomplete deserializations that lack the state property.
During planStartupCatchup(), the scheduler retrieves job records and attempts to access job.state.runningAtMs. When the job object has been replaced with a version missing the state field, the property access returns undefined, triggering the TypeError.
Secondary Failure Chain:
- Gateway process restarts
- Gateway RPC triggers cron subsystem restart
- Cron restart invokes
runMissedJobs()during initialization - TypeError crashes cron worker
- WebSocket handshake for CLI connections never completes
- CLI hangs waiting for RPC response
Regression Analysis: This bug did not exist in OpenClaw 3.29 but manifests in 2026.4.9, indicating a regression introduced in the cron subsystem between these versions.
🛠️ Fix
Workaround A: Direct jobs.json Modification (Recommended)
- Locate the
jobs.jsonfile in the container volume mount - Stop the gateway container to prevent write conflicts
- Edit
jobs.jsondirectly with a text editor - Add the required
stateobject to each job entry:{ "state": { "runningAtMs": null, "lastRunMs": 0 } } - Restart the gateway container using
docker-compose restartordocker kill -s SIGTERM <container_id>
Workaround B: Bypass CLI WebSocket
- Use direct HTTP API calls instead of CLI commands during the crash window
- Avoid running
openclaw cron addoropenclaw cron listwhile cron is unstable - Use
curlorwgetto query cron status via the gateway HTTP endpoint
Workaround C: Version Rollback
- Downgrade to OpenClaw 3.29 where the cron scheduler functions correctly
- Use Docker image tag pinning:
image: openclaw:3.29 - Restore jobs from backup if available
Prevention: Avoid gateway restarts while cron jobs are in a transitional state. Implement health checks that verify cron subsystem stability before restarting dependent services.