Task Scheduler is one of those things you configure once and forget. You set the trigger, point it at a script, Windows runs it on schedule forever. Permanent infrastructure. That’s been my mental model since maybe 2003. It was wrong.
A few weeks into running HP Klaus on Windows-native, I ran schtasks /query /fo LIST | findstr "Task Name" just to take stock of what was registered. I expected maybe eight or ten entries. What I got was closer to forty.
I started going through the list. A lot of the same task name, over and over. Not similar. Identical. Same trigger. Same script path. Same everything. Fifteen copies of the same scheduled job.
What happened makes sense in retrospect. Klaus sets up automation tasks during session work. If a session starts without context about what’s already registered on the machine, it checks what should be running, doesn’t find it in current memory, and creates the task fresh. Windows Task Scheduler doesn’t refuse a duplicate name. It just adds another entry. Fifteen sessions across several weeks, fifteen entries. All running. All firing at the same interval.
The practical effect is mostly harmless. Most of my scheduled scripts are idempotent. Check for work, find none, exit clean. Running them fifteen times in a row doesn’t do anything different from running them once. But one script rotates log files by size. Fifteen runs in five minutes means tighter rotation than I intended, more files, faster churn. Not broken. Just wrong.
There’s a cleanup script. remove-duplicate-tasks.ps1, sitting in the repo, scoped to the known duplicates. It needs admin access to modify Task Scheduler entries. I haven’t gotten around to granting it. So the fifteen-headed schedule is still running, and the fix is waiting on me to do one thing.
Don’t get me wrong, this one’s on me, not Klaus. The setup scripts didn’t include an idempotency check. Before creating a Task Scheduler entry, the right move is to check if it’s already there: schtasks /query /tn "TaskName" 2>$null returns something if the task exists, nothing if it doesn’t. One conditional. That’s it. I didn’t write it. So the scripts created state without checking for existing state, and then ran in sessions that had no memory of prior runs. Of course they duplicated.
The AI did exactly what the scripts told it to do. The scripts just assumed they were always starting from zero.
Write your automation as if it’ll run on a machine that’s already run it. Because at some point, it will.