Skip to content

fix(cron): prevent premature cron job fire on restart (#60985)#2

Open
rockcent wants to merge 1749 commits intomainfrom
fix/cron-startup-missed-run-guard
Open

fix(cron): prevent premature cron job fire on restart (#60985)#2
rockcent wants to merge 1749 commits intomainfrom
fix/cron-startup-missed-run-guard

Conversation

@rockcent
Copy link
Copy Markdown
Owner

@rockcent rockcent commented Apr 4, 2026

Summary

Fixes a regression where a cron job that already ran at its scheduled time would incorrectly fire again immediately on gateway restart.

Bug Description

When the gateway restarts before a cron job's scheduled time, the job was incorrectly identified as a "missed" job and fired immediately on startup catch-up, even though:

  1. The job already ran at its scheduled time yesterday
  2. The next scheduled time is still hours away

Root Cause: In isRunnableJob(), the allowCronMissedRunByLastRun path computed previousRunAtMs from nowMs instead of from nextRunAtMs. When nowMs is before the scheduled time (e.g., 01:24 AM for a 09:00 AM job), previousRunAtMs incorrectly returned yesterday's scheduled slot — the same as lastRunAtMs. The condition previousRunAtMs > lastRunAtMs evaluated to false... but the subsequent guard was absent, allowing the false-positive catch-up.

The Fix:

  1. Compute previousRunAtMs from nextRunAtMs instead of nowMs — this correctly contexts the previous occurrence relative to the upcoming scheduled slot
  2. Add a lastRunAtMs >= previousRunAtMs guard that returns false when the job already ran (either exactly at the scheduled slot or late after it)

Files Changed

Impact

  • Cron jobs will no longer fire prematurely on gateway restart
  • No breaking changes — the fix only removes false-positive catch-up runs

Related Issues

Fixes openclaw#60985

drvoss and others added 30 commits April 4, 2026 15:38
…penclaw#53395)

Merged via squash.

Prepared head SHA: 31f2396
Co-authored-by: drvoss <3031622+drvoss@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
…d ping intervals (openclaw#56646)

Merged via squash with admin override.

Prepared head SHA: f1c91d5
Note: required red lanes are currently inherited from latest origin/main, not introduced by this PR.
Co-authored-by: hsiaoa <70124331+hsiaoa@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
…penclaw#59911)

Merged via squash.

Prepared head SHA: a67bcaa
Co-authored-by: ejames-dev <180847219+ejames-dev@users.noreply.github.com>
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>
Reviewed-by: @hxy91819
…penclaw#60557)

Merged via squash.

Prepared head SHA: 637ff7d
Co-authored-by: feniix <91633+feniix@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
When the gateway client reconnects using a stored device token, it was
defaulting to ["operator.admin"] scopes instead of preserving the
previously authorized scopes from the stored token. This caused the
operator device token to be regenerated without operator.read scope,
breaking status/probe/health commands.

This fix:
1. Loads the stored scopes along with the stored token in selectConnectAuth
2. Uses the stored scopes when reconnecting with a valid device token
3. Falls back to explicitly requested scopes or default admin-only scope
   when no stored scopes exist

Fixes openclaw#46000
…odel (openclaw#58294)

* fix(cron): prevent agent default model from overriding cron payload model (openclaw#58065)

When a cron job specifies a model override via the Advanced settings,
runWithModelFallback could silently fall back to the agent's configured
primary model. This happened because fallbacksOverride was undefined
when neither payload.fallbacks nor per-agent fallbacks were configured,
causing resolveFallbackCandidates to append the agent primary as a
last-resort candidate. A transient failure on the cron-selected model
(rate limit, model-not-found, etc.) would then succeed on the agent
default, making it appear as if the override was ignored entirely.

Fix: when the cron payload carries an explicit model override, ensure
fallbacksOverride is always a defined array (empty when no fallbacks
are configured) so the agent primary is never silently appended.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: use stricter toEqual([]) assertion for fallbacksOverride

Replace toBeDefined() + toBeInstanceOf(Array) with toEqual([])
to catch regressions where the array unexpectedly gains entries.
Addresses review feedback.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: preserve cron override fallback semantics (openclaw#58294)

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
steipete and others added 30 commits April 4, 2026 19:20
…y ran

Fixes a regression where a cron job that already ran at its scheduled
time would incorrectly fire again immediately on gateway restart.

Root cause: isRunnableJob() computed previousRunAtMs from nowMs instead
of nextRunAtMs in the allowCronMissedRunByLastRun path. When nowMs
is before the scheduled time, previousRunAtMs incorrectly returned
yesterday's slot — the same as lastRunAtMs for a job that already ran.
The condition previousRunAtMs > lastRunAtMs evaluated to false, but
there was no guard to suppress the false-positive catch-up.

Fix: compute previousRunAtMs from nextRunAtMs (correct context) and
add a lastRunAtMs >= previousRunAtMs guard to prevent replay of a job
that already ran (at or after its scheduled slot).

Fixes openclaw#60985
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Cron jobs immediately fire on gateway restart instead of waiting for next scheduled time