#19541: fix: schedule nextWakeAtMs for isolated sessionTarget cron jobs
size: S
Cluster:
Cron Scheduler Improvements
## Summary
- repair cron scheduling when jobs carry non-finite `nextRunAtMs` values so the timer can arm and `nextWakeAtMs` is populated
- harden `every` schedule anchor fallback to use `nowMs` when external registrations omit `createdAtMs`
- treat invalid `nextRunAtMs` as missing during maintenance recompute so isolated jobs self-heal instead of silently stalling
- add a regression test covering isolated `every` jobs loaded without `createdAtMs`
## Testing
- `pnpm vitest run src/cron/service.issue-regressions.test.ts src/cron/service.every-jobs-fire.test.ts src/cron/service.issue-16156-list-skips-cron.test.ts src/cron/service.rearm-timer-when-running.test.ts src/cron/service.prevents-duplicate-timers.test.ts --config vitest.unit.config.ts`
- `pnpm vitest run src/cron/service/jobs.schedule-error-isolation.test.ts --config vitest.unit.config.ts`
- `pnpm vitest run --config vitest.e2e.config.ts src/gateway/server.cron.e2e.test.ts`
Fixes #19469
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Fixed cron scheduling for isolated jobs with non-finite timestamp values
This PR addresses an issue where isolated `sessionTarget` cron jobs could have invalid (non-finite) `nextRunAtMs` values, preventing the timer from arming properly and causing jobs to stall silently.
**Key Changes:**
- Added `isFiniteTimestamp()` type guard for consistent finite number validation across the cron service
- Hardened `resolveEveryAnchorMs()` to fall back to `0` when both `anchorMs` and `fallbackAnchorMs` are non-finite, ensuring `every` schedules can always compute a valid anchor
- Modified `computeJobNextRunAtMs()` to validate all return paths and only return finite timestamps or `undefined`
- Added cleanup logic in `normalizeJobTickState()` to treat non-finite `nextRunAtMs` as missing during maintenance passes
- Updated `nextWakeAtMs()` and `armTimer()` to filter out jobs with non-finite timestamps
- Added regression test covering isolated jobs missing `createdAtMs` that validates self-healing behavior
The fix ensures legacy jobs with invalid timestamps self-heal on next service start and prevents future invalid values from propagating through the scheduling system.
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with minimal risk
- The changes are defensive additions that make the cron scheduler more robust. All modifications add validation guards without changing core scheduling logic. The fix includes comprehensive test coverage for the regression case and the implementation consistently applies `Number.isFinite()` checks across all relevant code paths.
- No files require special attention
<sub>Last reviewed commit: 052b306</sub>
<!-- greptile_other_comments_section -->
<sub>(4/5) You can add custom instructions or style guidelines for the agent [here](https://app.greptile.com/review/github)!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#12131: fix(cron): ensure timer callback fires for scheduled jobs
by divol89 · 2026-02-08
81.8%
#18144: fix(cron): clear stuck runningAtMs after timeout and add maintenanc...
by taw0002 · 2026-02-16
81.8%
#11813: fix(cron): ensure 'at' schedule type correctly registers nextWakeAt...
by leo-reifying · 2026-02-08
81.7%
#12303: fix(cron): correct nextRunAtMs calculation and prevent timer stall
by colddonkey · 2026-02-09
81.1%
#23501: fix(cron): force new session ID for isolated cron jobs (#23470)
by stakeswky · 2026-02-22
81.0%
#12086: fix(cron): ensure timer callback fires for scheduled jobs
by divol89 · 2026-02-08
80.8%
#12122: fix(cron): ensure timer callback fires for scheduled jobs
by divol89 · 2026-02-08
80.5%
#23650: fix(cron): arm maintenance timer when enabled jobs lack nextRunAtMs
by taw0002 · 2026-02-22
80.4%
#14667: fix: preserve missed cron runs when updating job schedule
by WalterSumbon · 2026-02-12
80.4%
#8034: fix(cron): run past-due one-shot jobs immediately on startup
by FelixFoster · 2026-02-03
80.3%