Problem: Scheduled tasks are executed twice
Issue
Planned tasks are sometimes executed twice.
Impact
Service (scheduled tasks, alerts)
Installation method
Docker
Database
Postgres
Browser
No response
Semaphore Version
v2.12.14-685c726-1739570731
Ansible Version
Logs & errors
No response
Manual installation - system information
No response
Configuration
No response
Additional information
No response
HI @Skyfay I need more details to understand the problem. Which cron record used for this tasks?
Hey @fiftin
The Schedules looks like this:
I also don't understand why they are executed twice.
All I have is the following:
time="2025-03-24T02:10:00+01:00" level=info msg="Task 59 added to queue"
time="2025-03-24T02:10:01+01:00" level=info msg="Task 60 added to queue"
time="2025-03-24T02:10:01+01:00" level=info msg="Set resource locker with TaskRunner 59"
time="2025-03-24T02:10:01+01:00" level=info msg="Task 59 removed from queue"
time="2025-03-24T02:12:19+01:00" level=error msg="remove /tmp/semaphore/inventory_59: no such file or directory"
time="2025-03-24T02:12:19+01:00" level=info msg="Stopped running TaskRunner 59"
time="2025-03-24T02:12:19+01:00" level=info msg="Release resource locker with TaskRunner 59"
time="2025-03-24T02:12:21+01:00" level=info msg="Set resource locker with TaskRunner 60"
time="2025-03-24T02:12:21+01:00" level=info msg="Task 60 removed from queue"
time="2025-03-24T02:13:17+01:00" level=error msg="remove /tmp/semaphore/inventory_60: no such file or directory"
time="2025-03-24T02:13:17+01:00" level=info msg="Stopped running TaskRunner 60"
time="2025-03-24T02:13:17+01:00" level=info msg="Release resource locker with TaskRunner 60"
Template:
Schedule:
However, I have also seen these errors above with other tasks. I do not suspect that this has anything to do with it. The tasks also run successfully without any problems. I don't know why this output occurs.
(This is with version: v2.13.0-75ffe9c-1742166220)
Now another special thing, a task runs but it was disabled.
Maybe the schedule module is a little broken?
Hi @Skyfay maybe, but I can't reproduce the issue.
I can reproduce the same issue with scheduling, except it's scheduled 60 times for me (tasks 323 -> 383). I can confirm the enable/disable toggle works, but obviously something is very wrong in the scheduling. It also doesn't run the tasks sequentially which is a bit strange - though obviously secondary to the big scheduling issue. The problem is the cron is execuring every minute in the given hour, not just on the hour.
I initially suspected this code might be the culprit, but when I look within the database the cron is correct. https://github.com/semaphoreui/semaphore/blob/e23eda85b91f122d5b229e6c5bdfae5122755be7/.dredd/hooks/helpers.go#L201
I think what's happening is when the minutes isn't set, Semaphore is checking every minute and adding the task because it matches (it isn't looking if the task is already scheduled). When I add minutes to the task (00), it only executes once, at HH:00. - maybe just make this a default if nothing is selected?
time="2025-05-02T02:00:00-04:00" level=info msg="Task 324 added to queue"
time="2025-05-02T02:00:01-04:00" level=info msg="Set resource locker with TaskRunner 324"
time="2025-05-02T02:00:01-04:00" level=info msg="Task 324 removed from queue"
time="2025-05-02T02:01:00-04:00" level=info msg="Task 325 added to queue"
time="2025-05-02T02:02:00-04:00" level=info msg="Task 326 added to queue"
time="2025-05-02T02:03:00-04:00" level=info msg="Task 327 added to queue"
time="2025-05-02T02:04:00-04:00" level=info msg="Task 328 added to queue"
time="2025-05-02T02:05:00-04:00" level=info msg="Task 329 added to queue"
time="2025-05-02T02:06:00-04:00" level=info msg="Task 330 added to queue"
time="2025-05-02T02:07:00-04:00" level=info msg="Task 331 added to queue"
time="2025-05-02T02:08:00-04:00" level=info msg="Task 332 added to queue"
time="2025-05-02T02:09:00-04:00" level=info msg="Task 333 added to queue"
time="2025-05-02T02:10:00-04:00" level=info msg="Task 334 added to queue"
time="2025-05-02T02:11:00-04:00" level=info msg="Task 335 added to queue"
time="2025-05-02T02:12:00-04:00" level=info msg="Task 336 added to queue"
time="2025-05-02T02:13:00-04:00" level=info msg="Task 337 added to queue"
time="2025-05-02T02:14:00-04:00" level=info msg="Task 338 added to queue"
time="2025-05-02T02:15:00-04:00" level=info msg="Task 339 added to queue"
time="2025-05-02T02:16:00-04:00" level=info msg="Task 340 added to queue"
time="2025-05-02T02:17:00-04:00" level=info msg="Task 341 added to queue"
time="2025-05-02T02:18:00-04:00" level=info msg="Task 342 added to queue"
time="2025-05-02T02:19:00-04:00" level=info msg="Task 343 added to queue"
time="2025-05-02T02:20:00-04:00" level=info msg="Task 344 added to queue"
time="2025-05-02T02:21:00-04:00" level=info msg="Task 345 added to queue"
time="2025-05-02T02:22:00-04:00" level=info msg="Task 346 added to queue"
time="2025-05-02T02:23:00-04:00" level=info msg="Task 347 added to queue"
time="2025-05-02T02:24:00-04:00" level=info msg="Task 348 added to queue"
time="2025-05-02T02:25:00-04:00" level=info msg="Task 349 added to queue"
time="2025-05-02T02:26:00-04:00" level=info msg="Task 350 added to queue"
time="2025-05-02T02:27:00-04:00" level=info msg="Task 351 added to queue"
time="2025-05-02T02:28:00-04:00" level=info msg="Task 352 added to queue"
time="2025-05-02T02:29:00-04:00" level=info msg="Task 353 added to queue"
time="2025-05-02T02:30:00-04:00" level=info msg="Task 354 added to queue"
time="2025-05-02T02:31:00-04:00" level=info msg="Task 355 added to queue"
time="2025-05-02T02:32:00-04:00" level=info msg="Task 356 added to queue"
time="2025-05-02T02:33:00-04:00" level=info msg="Task 357 added to queue"
time="2025-05-02T02:34:00-04:00" level=info msg="Task 358 added to queue"
time="2025-05-02T02:35:00-04:00" level=info msg="Task 359 added to queue"
time="2025-05-02T02:36:00-04:00" level=info msg="Task 360 added to queue"
time="2025-05-02T02:37:00-04:00" level=info msg="Task 361 added to queue"
time="2025-05-02T02:38:00-04:00" level=info msg="Task 362 added to queue"
time="2025-05-02T02:39:00-04:00" level=info msg="Task 363 added to queue"
time="2025-05-02T02:40:00-04:00" level=info msg="Task 364 added to queue"
time="2025-05-02T02:40:59-04:00" level=info msg="Stopped running TaskRunner 324"
time="2025-05-02T02:40:59-04:00" level=info msg="Release resource locker with TaskRunner 324"
time="2025-05-02T02:41:00-04:00" level=info msg="Task 365 added to queue"
time="2025-05-02T02:41:01-04:00" level=info msg="Set resource locker with TaskRunner 335"
time="2025-05-02T02:41:01-04:00" level=info msg="Task 335 removed from queue"
time="2025-05-02T02:42:00-04:00" level=info msg="Task 366 added to queue"
time="2025-05-02T02:43:00-04:00" level=info msg="Task 367 added to queue"
time="2025-05-02T02:44:00-04:00" level=info msg="Task 368 added to queue"
time="2025-05-02T02:45:00-04:00" level=info msg="Task 369 added to queue"
time="2025-05-02T02:46:00-04:00" level=info msg="Task 370 added to queue"
time="2025-05-02T02:47:00-04:00" level=info msg="Task 371 added to queue"
time="2025-05-02T02:48:00-04:00" level=info msg="Task 372 added to queue"
time="2025-05-02T02:49:00-04:00" level=info msg="Task 373 added to queue"
time="2025-05-02T02:50:00-04:00" level=info msg="Task 374 added to queue"
time="2025-05-02T02:51:00-04:00" level=info msg="Task 375 added to queue"
time="2025-05-02T02:52:00-04:00" level=info msg="Task 376 added to queue"
time="2025-05-02T02:53:00-04:00" level=info msg="Task 377 added to queue"
time="2025-05-02T02:54:00-04:00" level=info msg="Task 378 added to queue"
time="2025-05-02T02:55:00-04:00" level=info msg="Task 379 added to queue"
time="2025-05-02T02:56:00-04:00" level=info msg="Task 380 added to queue"
time="2025-05-02T02:57:00-04:00" level=info msg="Task 381 added to queue"
time="2025-05-02T02:58:00-04:00" level=info msg="Task 382 added to queue"
time="2025-05-02T02:59:00-04:00" level=info msg="Task 383 added to queue"
time="2025-05-02T03:21:22-04:00" level=info msg="Stopped running TaskRunner 335"
time="2025-05-02T03:21:22-04:00" level=info msg="Release resource locker with TaskRunner 335"
time="2025-05-02T03:21:26-04:00" level=info msg="Set resource locker with TaskRunner 338"
time="2025-05-02T03:21:26-04:00" level=info msg="Task 338 removed from queue"
Maybe have something to do with this:
Since i disabled this i didn't have the error that the task was executed twice.
@Skyfay is it solved?
@fiftin Just adding a note that might help others who run into the same issue - I was able to reproduce it as well.
The fix from @Skyfay works, but I kept seeing the issue reappear whenever I restored my Semaphore project from a backup. Each time I restored, the problem came back.
After taking a closer look at my backup file today, I noticed that the task causing the issue had a cron expression under "cron" in the template - matching the schedule’s cron time - instead of using the fixed interval that should normally be set from the frontend. Despite "autorun": false, Semaphore still executed the task automatically.
In the UI, this appeared as the checkbox for “I want to run a task by the cron...” being checked, but the "checkInterval" field left empty. In my backup file, it looked like this:
...
"schedules": [
{
"active": true,
"cron_format": "0 5 10 * *",
"name": "Update non-automatic Machines - Monthly",
"task_params": {
"environment": "",
"message": "",
"params": {}
},
"template": "Update non-automatic Machines"
}
],
"templates": [
{
"allow_override_args_in_task": false,
"allow_override_branch_in_task": false,
"allow_parallel_tasks": false,
"app": "ansible",
"arguments": "[]",
"autorun": false,
"cron": "0 5 10 * *",
"environment": "Empty",
"inventory": "develop",
"name": "Update non-automatic Machines",
"playbook": "update-non-automatic.yaml",
"repository": "Ansible HomeLab",
"suppress_success_alerts": false,
"survey_vars": [],
"task_params": {},
"type": "",
"vaults": []
}
],
...
As you can see, .schedules[0].cron_format and .templates[0].cron are identical, and it seems that the value in .templates[0].cron overrides the autorun setting, causing it to run regardless.
The fix for me was simply to remove .templates[0].cron entirely.
I suspect this happened because I created the backup before a bug was fixed that should have prevented such a configuration in the first place. The restore process doesn’t seem to validate or clean up edge cases like this - though technically, it did exactly what I told it to with that backup file 😄.