enabled: false Silently Disabled Claude Code Scheduled Tasks A team running a blog at tech.rebounder.jp documented seven weeks of operating six daily Claude Code scheduled tasks unattended and found they fail in three distinct ways: slots skipped while the Mac sleeps (which auto-run on next launch), runs that die mid-execution on dropped connections with no retry, and slots silently flipped to enabled: false without anyone intending it. The most damaging case went unnoticed for a week on 2026-09-27–28, when three of four article-writing slots were disabled and daily output fell to exactly one article, because the monitoring dashboard rendered it identically to a connection failure. The team now counts published articles against elapsed slots at the start of each run, caps catch-up at two articles, pulls Cloudflare traffic numbers first since they expire after seven days, and re-enables any disabled slot not listed as an exception in the runbook. Running Claude Code's scheduled tasks unattended, we found they stop three different ways . | How it stops | What happened | Fix needed | |---|---|---| | ① Never starts | Mac was asleep, or the app was closed | None — it runs automatically on the next launch | | ② Starts, then dies mid-run | A dropped connection, so the API was never reached | No retry exists. The next slot has to catch up | | ③ The slot itself gets disabled | enabled: false , with no one intending it | Check the list daily and re-enable | None of the three show up in the log of the run that actually happened. That's why we judge by "did the artifact land in git" instead of "did it run." This blog's tech.rebounder.jp articles are written by scheduled tasks in Claude Code's desktop app. There are 6 slots a day: 4 for writing articles 08:06 / 12:08 / 16:05 / 20:07 and 2 for stocking angles and pulling traffic numbers 11:02 / 17:07 . We've run this setup for 7 weeks starting 2026-08-16. Every run happens with no screen , and no human is in the loop. So we can't assume "someone will notice" when something stops. If the Mac is asleep or the app is closed, nothing happens at that time. But this ran automatically the next time the app launched . In one measurement, the 8/17 20:07 slot completed on 8/18 at 09:59. This isn't the one that needs attention. This is the one that hurts. The 2026-08-17 20:02 night slot died 4 minutes after starting, with this error: API Error: Can't reach the API server ENOTFOUND The log was 12 lines, and not a single file had been touched. It died, so it couldn't record anything itself. Two days later, on 8/19, the connection dropped for about an hour, and the 11:02 and 12:08 slots died back to back. There was no retry, and that slot was lost for good. Because the run itself dies before reaching the API, writing "retry on failure" into the runbook doesn't help either — there's no process left to read it. The only lever we had was "the next slot catches up." Now, at the start of every slot, we count how many articles have gone out today and how many slots have already passed, and write the shortfall in that slot . We capped the catch-up at 2 articles per run , for three reasons: We also changed the order. Traffic numbers only last 7 days on the Cloudflare side, so a day you miss is gone forever. An article, on the other hand, can always be carried over to the next day. So after the 8/19 miss, we made every article-writing slot pull the traffic numbers first, before touching the article. If even one of the 4 slots runs, that day's data is captured. The 8/18 10:01 stocking slot has an execution record a last-run timestamp showing it ran, but it neither stocked angles nor pulled traffic — it just wrote one file and stopped. It had overlapped with a carried-over run which finished at 10:02 . If you only look at the execution record, this looks like a success. This is the one we missed longest. On 2026-09-27–28, 3 of the 4 article-writing slots had been set to enabled: false . We didn't notice for a week. Daily output dropped from 1–4 articles a day to exactly 1 a day. The 5 runs right before that had all succeeded — this wasn't caused by a failure. No one remembered disabling it, either. No one intended to stop it. Our monitoring dashboard did render this as a "failure." But it looked identical to a run that died from a dropped connection , so it got lost among 16 other entries. The root problem was that we weren't distinguishing "one run failed" from "the slot itself is disabled." Now, at the start of the first slot each day, we list every scheduled task. If a writing slot is set to false , we flip it back to true and add one line to the report: "X was disabled, so I re-enabled it." If we ever want a slot intentionally stopped, its name goes into the runbook as an exception. Any slot not named there gets flipped back on every day. What all three have in common is that trusting the run's own record misses things. A run that died can't record anything, and a run that merely executed will call itself a "success." So for every slot we decided which file should land in git if that slot actually did its job — an article file for a writing slot, measurement data for a stocking slot — and we judge by whether that file showed up. The morning and evening stocking slots write to the same kind of file, so they wouldn't be distinguishable from each other; we gave them separate heartbeat files instead. We'd originally guessed 120 minutes as the time from "run starts" to "artifact appears." Here's what we actually measured from 8/17–8/30: | Slot | Median | Max | |---|---|---| | 08:06 morning article | 13 min | 113 min | | 11:02 stocking | 107 min | 171 min | | 12:08 midday article | 78 min | 125 min | | 16:05 evening article | 122 min | 163 min | | 17:07 evening stocking | 68 min | 130 min | | 20:07 night article | 19 min | 169 min | The evening article slot's median exceeded the window itself. Articles were going out, but more than half were showing up as "failed," reporting a 33% success rate. We widened the window to 180 minutes and the false alarms went away. A dashboard that cries wolf eventually gets ignored by everyone. Separate from the three ways of stopping, on day one 2026-08-16 we hit a permission check. Since no one can approve anything in an unattended run, the slot just ends the moment a confirmation prompt appears. There were two causes: && or ; cd