openclaw - ✅(Solved) Fix [Bug]: Cron jobs are not executing as scheduled. [2 pull requests, 1 comments, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#58833Fetched 2026-04-08 02:32:10
View on GitHub
Comments
1
Participants
1
Timeline
7
Reactions
0
Participants
Timeline (top)
cross-referenced ×2labeled ×2closed ×1locked ×1

OpenClaw Cron 调度时间偏移严重,执行时间记录不准确

Root Cause

OpenClaw Cron 调度时间偏移严重,执行时间记录不准确

Fix Action

Fixed

PR fix notes

PR #58872: fix(cron): avoid busy-wait drift for recurring main jobs

Description (problem / solution / changelog)

Summary

  • Problem: recurring main-session cron jobs with --wake now stay inside the cron run while runHeartbeatOnce keeps returning requests-in-flight, which inflates lastDurationMs and lets schedule drift accumulate.
  • Why it matters: short recurring jobs like */3 * * * * can appear to run for minutes and miss later slots even with --exact.
  • What changed: recurring main-session jobs now fall back to requestHeartbeatNow() immediately after the first busy runHeartbeatOnce result instead of busy-waiting in the cron lane.
  • What did NOT change (scope boundary): one-shot --at jobs still keep the existing synchronous wait-for-heartbeat behavior.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #58833
  • Related #58833
  • This PR fixes a bug or regression

Root Cause / Regression History (if applicable)

  • Root cause: executeMainSessionCronJob() retried runHeartbeatOnce() for up to the busy-wait window even for recurring jobs, so the cron run duration included main-lane contention instead of just cron scheduling work.
  • Missing detection / guardrail: there was coverage for one-shot wakeMode=now behavior, but no regression test for recurring main-session jobs under requests-in-flight pressure.
  • Prior context (git blame, prior PR, issue, or refactor if known): Unknown.
  • Why this regressed now: under heavier gateway load, recurring cron jobs can hit the busy main lane path repeatedly, which magnifies duration inflation and drift.
  • If unknown, what was ruled out: the per-job cron stagger path and post-run duration math were not the primary cause here.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/cron/service.issue-regressions.test.ts
  • Scenario the test should lock in: a recurring main-session cron job with wakeMode="now" and runHeartbeatOnce() returning requests-in-flight should request a queued heartbeat immediately and complete with a short recorded duration.
  • Why this is the smallest reliable guardrail: it exercises the exact scheduler path without requiring broader gateway/runtime setup.
  • Existing test that already covers this (if any): src/cron/service.runs-one-shot-main-job-disables-it.test.ts covers one-shot wakeMode now behavior, but not recurring jobs.
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

Recurring main-session cron jobs using --wake now no longer sit in a long busy-wait loop when the main lane is already busy. Their cron run finishes quickly after queueing the immediate heartbeat, which keeps lastDurationMs closer to scheduler overhead and reduces drift from blocked cron slots.

Diagram (if applicable)

Before:
[recurring cron due] -> [enqueue system event] -> [busy runHeartbeatOnce loop] -> [minutes counted as cron duration] -> [later slots drift]

After:
[recurring cron due] -> [enqueue system event] -> [first busy runHeartbeatOnce] -> [requestHeartbeatNow] -> [cron run completes quickly]

Security Impact (required)

  • New permissions/capabilities? (Yes/No) No
  • Secrets/tokens handling changed? (Yes/No) No
  • New/changed network calls? (Yes/No) No
  • Command/tool execution surface changed? (Yes/No) No
  • Data access scope changed? (Yes/No) No
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: local test runner
  • Model/provider: N/A
  • Integration/channel (if any): N/A
  • Relevant config (redacted): recurring main-session cron job with wakeMode=now

Steps

  1. Create a recurring main-session cron job with wakeMode=now.
  2. Make runHeartbeatOnce() return { status: "skipped", reason: "requests-in-flight" }.
  3. Execute the job and inspect the recorded result.

Expected

  • The cron job should enqueue the event, request an immediate heartbeat, and finish quickly.

Actual

  • Before this change, the cron job stayed in the busy-wait retry loop and recorded an inflated duration.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios: ran pnpm test -- src/cron/service.issue-regressions.test.ts -t "#58833|busy-recurring-main|main lane is busy" and pnpm test -- src/cron/service.runs-one-shot-main-job-disables-it.test.ts -t "wakeMode now".
  • Edge cases checked: confirmed the existing one-shot wakeMode now tests still pass, so the synchronous one-shot behavior remains intact.
  • What you did not verify: full repo-wide pnpm check is currently failing due to unrelated existing tsgo errors outside the cron surface.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? (Yes/No) Yes
  • Config/env changes? (Yes/No) No
  • Migration needed? (Yes/No) No
  • If yes, exact upgrade steps:

Risks and Mitigations

  • Risk: recurring main-session jobs now stop waiting sooner when the main lane is busy, so their cron run status reflects successful queueing rather than completed main-lane processing.
    • Mitigation: the change is limited to recurring jobs; one-shot jobs keep the existing wait-for-heartbeat behavior, and the new regression test locks in the intended fallback path.

Changed files

  • src/cron/service.issue-regressions.test.ts (modified, +55/-0)
  • src/cron/service/timer.ts (modified, +12/-0)

PR #58725: Fix: slash commands ignored when wrapped by metadata text (Resolves #58674)

Description (problem / solution / changelog)

Fixes #58674.

Problem

Slash commands like /model spark and /new spark were silently ignored when the inbound message body included metadata prefix blocks (e.g. Conversation info (untrusted metadata):, Sender (untrusted metadata):, timestamps) injected by buildInboundUserContextPrefix. This happened because normalizeCommandBody returns text unchanged when it doesn't start with /, so metadata-wrapped commands were never parsed.

Fix

Applied stripInboundMetadata() (which already exists in strip-inbound-meta.ts) before calling normalizeCommandBody() in three locations:

  • hasControlCommand() in command-detection.ts
  • isControlCommandMessage() in command-detection.ts
  • parseSendPolicyCommand() in send-policy.ts

Tests

Added 3 test cases to command-control.test.ts covering:

  • Commands wrapped in Conversation info metadata blocks
  • Commands after Sender metadata prefix
  • Commands after timestamp + metadata prefix

Changed files

  • .agents/skills/openclaw-parallels-smoke/SKILL.md (modified, +6/-2)
  • .agents/skills/openclaw-release-maintainer/SKILL.md (modified, +21/-11)
  • .github/workflows/openclaw-npm-release.yml (modified, +57/-1)
  • .github/workflows/plugin-npm-release.yml (modified, +3/-0)
  • .markdownlint-cli2.jsonc (modified, +3/-0)
  • AGENTS.md (modified, +1/-1)
  • CHANGELOG.md (modified, +330/-163)
  • CONTRIBUTING.md (modified, +4/-1)
  • Dockerfile (modified, +1/-1)
  • Makefile (added, +4/-0)
  • README.md (modified, +44/-3)
  • SECURITY.md (modified, +5/-1)
  • appcast.xml (modified, +117/-42)
  • apps/android/app/build.gradle.kts (modified, +2/-2)
  • apps/android/app/src/main/java/ai/openclaw/app/MainViewModel.kt (modified, +1/-0)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/ConnectTabScreen.kt (modified, +8/-3)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/GatewayConfigResolver.kt (modified, +19/-5)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/OnboardingFlow.kt (modified, +5/-2)
  • apps/android/app/src/test/java/ai/openclaw/app/ui/GatewayConfigResolverTest.kt (modified, +82/-6)
  • apps/android/app/src/test/java/ai/openclaw/app/ui/OnboardingFlowLogicTest.kt (added, +27/-0)
  • apps/ios/Config/Version.xcconfig (modified, +3/-3)
  • apps/ios/README.md (modified, +3/-3)
  • apps/ios/Sources/Gateway/GatewaySettingsStore.swift (modified, +20/-0)
  • apps/ios/Sources/Model/NodeAppModel.swift (modified, +149/-13)
  • apps/ios/Sources/Settings/SettingsTab.swift (modified, +5/-0)
  • apps/ios/Tests/GatewayConnectionSecurityTests.swift (modified, +19/-2)
  • apps/ios/Tests/NodeAppModelInvokeTests.swift (modified, +58/-0)
  • apps/macos/Sources/OpenClaw/AppState.swift (modified, +13/-0)
  • apps/macos/Sources/OpenClaw/Constants.swift (modified, +1/-0)
  • apps/macos/Sources/OpenClaw/GatewayConnection.swift (modified, +4/-0)
  • apps/macos/Sources/OpenClaw/HostEnvSecurityPolicy.generated.swift (modified, +45/-0)
  • apps/macos/Sources/OpenClaw/Resources/Info.plist (modified, +2/-2)
  • apps/macos/Sources/OpenClaw/TalkModeController.swift (modified, +6/-0)
  • apps/macos/Sources/OpenClaw/TalkModeRuntime.swift (modified, +6/-0)
  • apps/macos/Sources/OpenClaw/VoiceWakeRuntime.swift (modified, +18/-1)
  • apps/macos/Sources/OpenClaw/VoiceWakeSettings.swift (modified, +10/-0)
  • apps/macos/Sources/OpenClawDiscovery/WideAreaGatewayDiscovery.swift (modified, +22/-74)
  • apps/macos/Tests/OpenClawIPCTests/WideAreaGatewayDiscoveryTests.swift (modified, +79/-1)
  • apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayTLSPinning.swift (modified, +31/-0)
  • docs/.generated/config-baseline.json (modified, +852/-475)
  • docs/.generated/config-baseline.jsonl (modified, +104/-76)
  • docs/.generated/plugin-sdk-api-baseline.json (modified, +131/-131)
  • docs/.generated/plugin-sdk-api-baseline.jsonl (modified, +125/-125)
  • docs/assets/sponsors/blacksmith-light.svg (added, +14/-0)
  • docs/assets/sponsors/convex-light.svg (added, +16/-0)
  • docs/assets/sponsors/nvidia-dark.svg (added, +9/-0)
  • docs/assets/sponsors/nvidia.svg (added, +9/-0)
  • docs/assets/sponsors/openai-light.svg (added, +3/-0)
  • docs/assets/sponsors/vercel-light.svg (added, +5/-0)
  • docs/automation/clawflow.md (modified, +47/-0)
  • docs/automation/cron-jobs.md (modified, +3/-1)
  • docs/automation/hooks.md (modified, +5/-0)
  • docs/automation/tasks.md (modified, +14/-0)
  • docs/channels/feishu.md (modified, +32/-0)
  • docs/channels/index.md (modified, +1/-1)
  • docs/channels/matrix.md (modified, +1/-0)
  • docs/channels/msteams.md (modified, +13/-0)
  • docs/channels/qqbot.md (modified, +48/-15)
  • docs/channels/troubleshooting.md (modified, +13/-0)
  • docs/channels/whatsapp.md (modified, +27/-1)
  • docs/cli/acp.md (modified, +2/-1)
  • docs/cli/cron.md (modified, +1/-1)
  • docs/cli/flows.md (modified, +1/-1)
  • docs/cli/plugins.md (modified, +12/-0)
  • docs/cli/skills.md (modified, +4/-0)
  • docs/concepts/model-failover.md (modified, +8/-0)
  • docs/concepts/models.md (modified, +1/-0)
  • docs/gateway/configuration-reference.md (modified, +4/-0)
  • docs/gateway/discovery.md (modified, +2/-0)
  • docs/gateway/doctor.md (modified, +8/-0)
  • docs/gateway/security/index.md (modified, +5/-1)
  • docs/gateway/tools-invoke-http-api.md (modified, +25/-9)
  • docs/gateway/trusted-proxy-auth.md (modified, +12/-0)
  • docs/help/faq.md (modified, +2/-0)
  • docs/help/testing.md (modified, +2/-2)
  • docs/install/development-channels.md (modified, +3/-3)
  • docs/platforms/mac/skills.md (modified, +1/-0)
  • docs/platforms/macos.md (modified, +2/-0)
  • docs/plugins/architecture.md (modified, +2/-0)
  • docs/plugins/sdk-channel-plugins.md (modified, +22/-2)
  • docs/providers/bedrock.md (modified, +41/-0)
  • docs/reference/RELEASING.md (modified, +6/-2)
  • docs/reference/prompt-caching.md (modified, +14/-4)
  • docs/reference/secretref-credential-surface.md (modified, +0/-4)
  • docs/reference/secretref-user-supplied-credentials-matrix.json (modified, +0/-28)
  • docs/start/openclaw.md (modified, +7/-4)
  • docs/tools/acp-agents.md (modified, +2/-0)
  • docs/tools/exec-approvals.md (modified, +1/-1)
  • docs/tools/exec.md (modified, +1/-1)
  • docs/tools/lobster.md (modified, +2/-0)
  • docs/tools/plugin.md (modified, +11/-0)
  • docs/tools/skills.md (modified, +2/-0)
  • docs/tools/slash-commands.md (modified, +2/-0)
  • docs/tools/web.md (modified, +37/-0)
  • extensions/acpx/package.json (modified, +2/-2)
  • extensions/acpx/src/runtime-internals/process.test.ts (modified, +30/-0)
  • extensions/acpx/src/runtime-internals/process.ts (modified, +8/-1)
  • extensions/acpx/src/runtime.test.ts (modified, +78/-0)
  • extensions/acpx/src/runtime.ts (modified, +29/-2)
  • extensions/acpx/src/service.test.ts (modified, +134/-0)

Code Example

{
  "name": "shanghai-weather-email-3min",
  "schedule": {
    "kind": "cron",
    "expr": "*/3 * * * *",
    "tz": "Asia/Shanghai",
    "staggerMs": 0  // 使用 --exact 参数设置
  },
  "state": {
    "lastRunAtMs": 1775027671714,  // 2026-04-01 15:14:31
    "lastDurationMs": 144936,      // 145秒(实际仅需1秒)
    "lastRunStatus": "ok"
  }
}


### Steps to reproduce

---

[2026-04-01 14:40:09] 🚀 开始执行 → [2026-04-01 14:40:10] 🏁 脚本执行完成 (1)
[2026-04-01 14:58:28] 🚀 开始执行 → [2026-04-01 14:58:29] 🏁 脚本执行完成 (1)

---

# 在系统crontab中
*/3 * * * * /path/to/script.sh

---
RAW_BUFFERClick to expand / collapse

Bug type

Regression (worked before, now fails)

Beta release blocker

No

Summary

OpenClaw Cron 调度时间偏移严重,执行时间记录不准确

问题描述

配置为每3分钟执行一次的OpenClaw cron任务,实际执行间隔严重偏离(如:14:40 → 14:58,间隔18分钟)。即使使用 --exact 参数禁用随机延迟,任务仍无法按预期频率执行。

环境信息

  • OpenClaw版本: 2026.3.23-2 (7ffe7e4)
  • 操作系统: macOS 25.3.0 (Darwin Kernel Version 25.3.0, ARM64)
  • Node.js版本: v24.14.0
  • Shell: zsh

复现步骤

  1. 创建一个简单的shell脚本(执行时间约1-2秒)
  2. 添加cron任务:openclaw cron add --name "test-task" --cron "*/3 * * * *" --system-event "/path/to/script.sh"
  3. 监控任务执行日志和OpenClaw状态

预期行为

  • 任务每3分钟准时执行一次(每分钟的0、3、6、9、12...秒)
  • lastDurationMs 准确反映脚本实际执行时间(1-2秒)

实际行为

时间偏移问题

  • 配置:*/3 * * * *(每3分钟)
  • 实际执行:14:40 → 14:58 → 下一次未知(间隔18分钟,严重偏离)
  • 即使使用 --exact --staggerMs 0,任务仍不能准时执行

执行时间记录错误

  • 脚本实际执行时间:1-2秒(日志确认)
  • OpenClaw记录的 lastDurationMs:145秒、237秒等(严重夸大)
  • 这可能导致调度器误认为任务仍在运行,跳过后续触发

相关配置与日志

任务配置(JSON片段)

{
  "name": "shanghai-weather-email-3min",
  "schedule": {
    "kind": "cron",
    "expr": "*/3 * * * *",
    "tz": "Asia/Shanghai",
    "staggerMs": 0  // 使用 --exact 参数设置
  },
  "state": {
    "lastRunAtMs": 1775027671714,  // 2026-04-01 15:14:31
    "lastDurationMs": 144936,      // 145秒(实际仅需1秒)
    "lastRunStatus": "ok"
  }
}


### Steps to reproduce

脚本日志(实际执行时间)

[2026-04-01 14:40:09] 🚀 开始执行 → [2026-04-01 14:40:10] 🏁 脚本执行完成 (1秒)
[2026-04-01 14:58:28] 🚀 开始执行 → [2026-04-01 14:58:29] 🏁 脚本执行完成 (1秒)

可能的原因分析

  1. 默认随机延迟机制:OpenClaw cron默认添加随机延迟(stagger),即使cron表达式精确
  2. 执行时间计算错误lastDurationMs 可能包括队列等待、进程启动等开销,而非仅脚本执行时间
  3. 调度器逻辑缺陷:如果任务记录的执行时间超过调度间隔,可能被误判为"仍在运行"而跳过
  4. 时间同步/时区处理:毫秒级时间戳转换或时区处理可能引入误差

影响

  1. 定时任务不可靠:无法依赖OpenClaw cron进行精确时间调度
  2. 监控误报:执行时间记录错误导致性能监控数据失真
  3. 任务堆积/丢失:长时间运行的任务可能阻塞后续执行,短时间任务可能被跳过

建议的解决方案

  1. 修复时间计算lastDurationMs 应准确反映用户脚本执行时间,不包括系统开销
  2. 改进调度算法:即使任务"记录"的运行时间超过间隔,也应检查进程实际状态
  3. 提供调试工具:如 openclaw cron debug <id> 查看详细调度时间线
  4. 文档明确说明:明确cron调度精度限制和stagger机制的影响

临时解决方法

目前用户不得不退回到系统cron(crontab)以获得精确调度:

# 在系统crontab中
*/3 * * * * /path/to/script.sh

附件

  • 完整脚本示例
  • OpenClaw cron list --json 输出
  • 详细执行日志

Expected behavior

应该为配置的时间触发

Actual behavior

时间不固定,会漂移

OpenClaw version

v2026.3.31 (running v2026.3.23-2).

Operating system

macos(26.3.1 (a) (25D771280a))

Install method

No response

Model

deepseek-reasoner

Provider / routing chain

https://api.deepseek.com

Additional provider/model setup details

No response

Logs, screenshots, and evidence

Impact and severity


优先级: High(影响核心调度功能) 分类: Bug / Cron调度器

Additional information

No response

extent analysis

TL;DR

临时解决方法是使用系统cron(crontab)以获得精确调度,等待OpenClaw官方修复时间计算和调度算法。

Guidance

  1. 检查OpenClaw版本: 确保使用的是最新版本的OpenClaw,以获取最新的bug修复和功能更新。
  2. 使用系统cron: 作为临时解决方法,使用系统cron(crontab)代替OpenClaw cron,以获得精确的调度。
  3. 监控OpenClaw更新: 关注OpenClaw的官方更新和发布说明,以获取关于cron调度器bug修复的信息。
  4. 提供反馈: 将遇到的问题和临时解决方法反馈给OpenClaw开发团队,以帮助他们改进产品。

Example

# 在系统crontab中添加以下行,以每3分钟执行一次脚本
*/3 * * * * /path/to/script.sh

Notes

  • OpenClaw的cron调度器目前存在时间偏移和执行时间记录错误的问题,需要等待官方修复。
  • 使用系统cron作为临时解决方法,可以保证精确的调度,但需要手动配置和管理。

Recommendation

Apply workaround: 使用系统cron(crontab)代替OpenClaw cron,以获得精确的调度,等待OpenClaw官方修复相关bug。

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

应该为配置的时间触发

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING