`lastDate()`/`lastExecution` does not reflect the last execution of the registered callback(s)
Description
As originally described in the issue https://github.com/kelektiv/node-cron/issues/710 the method lastDate() and therefore lastExecution indicate the moment when the last time was checked, if the next execution can be triggered and not when.
In the following section we are able to see that the lastExecution property will be set to the current Date before fireOnTick was even called.
https://github.com/kelektiv/node-cron/blob/d6f7c4aca9cd0d9a40a3cb8ee73c08e9be4ec3e9/src/job.ts#L336-L344
I think this is a bug as the variable name, lastExecution, and method description lastDate: Provides the last execution date. indicate information about the last execution rather the last tick as it's otherwise indicated by the methods
nextDate: Indicates the subsequent date that will activate anonTick.nextDates(count): Supplies an array of upcoming dates that will initiate an onTick.
I think currently we are seeing more likely the information about the lastTick or lastStart if you will.
Expected Behavior
lastDate() and lastExecution actually represent the moment when the callback(s) where invoked.
Actual Behavior
lastDate() and lastExecution represent the moment of the last check if the callback(s) can be invoked and will be updated on each iteration even without invoking any callback.
Possible Fix
Set lastExecution after setting _isCallbackRunning = true at:
https://github.com/kelektiv/node-cron/blob/d6f7c4aca9cd0d9a40a3cb8ee73c08e9be4ec3e9/src/job.ts#L248
Drop setting lastExecution at:
- https://github.com/kelektiv/node-cron/blob/d6f7c4aca9cd0d9a40a3cb8ee73c08e9be4ec3e9/src/job.ts#L130
- https://github.com/kelektiv/node-cron/blob/d6f7c4aca9cd0d9a40a3cb8ee73c08e9be4ec3e9/src/job.ts#L337
- https://github.com/kelektiv/node-cron/blob/d6f7c4aca9cd0d9a40a3cb8ee73c08e9be4ec3e9/src/job.ts#L367
Steps to Reproduce
import { CronJob } from 'cron';
console.log('=== Issue: lastExecution changes while callback is running ===\n');
console.log('Cron: every 5 seconds');
console.log('Callback: takes 60 seconds');
console.log('waitForCompletion: true (should prevent overlapping executions)\n');
let callbackStartTime: Date | null = null;
const callback = async () => {
callbackStartTime = new Date();
console.log(` Callback STARTED at: ${callbackStartTime.toISOString()}\n`);
await new Promise((resolve) => setTimeout(resolve, 60000)); // 60 seconds
console.log(` Callback COMPLETED at: ${new Date().toISOString()}\n`);
callbackStartTime = null;
};
const job = new CronJob('*/5 * * * * *', callback, null, true, null, null, false, null, false, true);
// Monitor every 2 seconds
setInterval(() => {
const now = new Date();
const actual = job.lastExecution;
const isRunning = job.isCallbackRunning;
if (!actual) return;
console.log(`[${now.toISOString()}]`);
console.log(` isCallbackRunning: ${isRunning}`);
console.log(` ACTUAL lastExecution: ${actual.toISOString()}`);
if (callbackStartTime) {
console.log(` EXPECTED lastExecution: ${callbackStartTime.toISOString()}`);
const diff = actual.getTime() - callbackStartTime.getTime();
if (Math.abs(diff) > 100) {
console.log(` ❌ DIFFERENCE: ${diff}ms`);
console.log(' ❌ lastExecution changed while callback is STILL RUNNING!');
} else {
console.log(' ✅ lastExecution matches callback start time');
}
}
console.log('');
}, 2000);
setTimeout(() => {
job.stop();
console.log('\n=== Summary ===');
console.log('Problem: lastExecution updates every 5s even though callback is still running');
console.log('Expected: lastExecution should stay constant until callback completes');
console.log('Solution: Set lastExecution in fireOnTick() after isCallbackRunning = true');
process.exit(0);
}, 65000);
Context
We want to monitor our cron's and know if they maybe take longer as they should or they are not invoked anymore besides that the callback is not running.
At least for us it's no solution to work with the threshold and timeout to execute the callback(s) even if its still running.
Your Environment
cronversion: 4.4.0- NodeJS version: 25.7.0
- Operating System and version: Debian 13
- TypeScript version (if applicable): 5.9.3
- Link to your project (if applicable): not possible to provide, sorry
Source: kelektiv/node-cron