Skip to content

[Bug] One-shot systemEvent cron jobs (deleteAfterRun) fire repeatedly on gateway restart #13845

@bruceeewong

Description

@bruceeewong

Bug Description

One-shot cron jobs (schedule.kind: "at" + deleteAfterRun: true + sessionTarget: "main" + payload.kind: "systemEvent") fire repeatedly when the gateway restarts after the scheduled time has passed.

The jobs get lastStatus: "skipped" (likely because the main session is busy), which does not count as a successful run, so deleteAfterRun never triggers. On each subsequent gateway restart, the overdue job is re-evaluated and re-injected, causing dozens of duplicate systemEvents.

Environment

  • OpenClaw Version: 2026.2.6-3
  • OS: macOS 15.7.3 (ARM64)
  • Node: v22.22.0
  • Channel: Telegram

Steps to Reproduce

  1. Create a one-shot reminder:
{
  "schedule": { "kind": "at", "at": "2026-02-10T22:30:00.000Z" },
  "payload": { "kind": "systemEvent", "text": "⏰ Reminder: Time to workout!" },
  "sessionTarget": "main",
  "deleteAfterRun": true
}
  1. Let the scheduled time pass while the main session is active (chatting with user)

  2. The systemEvent fires but gets lastStatus: "skipped"

  3. Restart the gateway (e.g., via config.patch or openclaw gateway restart)

  4. Observe: The same reminder fires again. Repeat step 4 → fires again each time.

In our case, multiple config changes triggered ~10 gateway restarts in an evening, resulting in 20+ duplicate reminder messages flooding the session.

Expected Behavior

  • Overdue at jobs with deleteAfterRun: true should be deleted (or at minimum disabled) after the scheduled time passes, regardless of whether the delivery was "skipped"
  • A systemEvent injection should not be skippable — it is a fire-and-forget text injection, not an agent turn that can fail

Actual Behavior

  • The job stays alive with lastStatus: "skipped" and deleteAfterRun never fires
  • Each gateway restart re-injects the systemEvent, causing duplicates
  • The only fix is manually removing the job via cron remove

Cron Job State After Bug

{
  "lastStatus": "skipped",
  "lastDurationMs": 0,
  "runningAtMs": 1770774567831
}

Workaround

Use sessionTarget: "isolated" + payload.kind: "agentTurn" instead of main + systemEvent for one-shot reminders. Isolated jobs complete independently and trigger deleteAfterRun correctly.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions