April 13, 2026 • Version: 2026.4.9

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:

  1. Gateway process restarts
  2. Gateway RPC triggers cron subsystem restart
  3. Cron restart invokes runMissedJobs() during initialization
  4. TypeError crashes cron worker
  5. WebSocket handshake for CLI connections never completes
  6. 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)

  1. Locate the jobs.json file in the container volume mount
  2. Stop the gateway container to prevent write conflicts
  3. Edit jobs.json directly with a text editor
  4. Add the required state object to each job entry:
    {
      "state": {
        "runningAtMs": null,
        "lastRunMs": 0
      }
    }
  5. Restart the gateway container using docker-compose restart or docker kill -s SIGTERM <container_id>

Workaround B: Bypass CLI WebSocket

  1. Use direct HTTP API calls instead of CLI commands during the crash window
  2. Avoid running openclaw cron add or openclaw cron list while cron is unstable
  3. Use curl or wget to query cron status via the gateway HTTP endpoint

Workaround C: Version Rollback

  1. Downgrade to OpenClaw 3.29 where the cron scheduler functions correctly
  2. Use Docker image tag pinning: image: openclaw:3.29
  3. 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.