CLAUDE LABJP
LIMITS — On August 29 Anthropic announced that from September 14 Claude Code's standard weekly limits rise permanently to 25% above the pre-promotion baseline, with the current 50% boost running through September 13LIMITS — In a follow-up the same day Anthropic put the same change at a 17% reduction compared with today. Both figures hold at once because they are measured from different starting pointsMATH — Index the pre-promotion limit at 100 and today sits at 150, with 125 arriving on September 14. That is 125 divided by 100 for the 25% rise, and 125 divided by 150 for the 17% drop against todaySCOPE — Only Claude Code's weekly limits change. The five-hour rolling window and the limits for Claude on web, desktop and mobile, and for Cowork, are all described as untouchedDOCS — As of August 30 the Help Center page still documented the boost as ending August 31. The announcement channel and the durable documentation do not move at the same speedRELEASE — Claude Code has shipped nothing new since v2.1.251 on August 28. With 26 releases in the past month, roughly one every 0.8 days, a two-day gap stands outLIMITS — On August 29 Anthropic announced that from September 14 Claude Code's standard weekly limits rise permanently to 25% above the pre-promotion baseline, with the current 50% boost running through September 13LIMITS — In a follow-up the same day Anthropic put the same change at a 17% reduction compared with today. Both figures hold at once because they are measured from different starting pointsMATH — Index the pre-promotion limit at 100 and today sits at 150, with 125 arriving on September 14. That is 125 divided by 100 for the 25% rise, and 125 divided by 150 for the 17% drop against todaySCOPE — Only Claude Code's weekly limits change. The five-hour rolling window and the limits for Claude on web, desktop and mobile, and for Cowork, are all described as untouchedDOCS — As of August 30 the Help Center page still documented the boost as ending August 31. The announcement channel and the durable documentation do not move at the same speedRELEASE — Claude Code has shipped nothing new since v2.1.251 on August 28. With 26 releases in the past month, roughly one every 0.8 days, a two-day gap stands out
Articles/Claude Code
Claude Code/2026-08-31Intermediate

Half of My Scheduled Runs Vanished Without a Single Error

A batch job set to run twice a day was only firing once. No errors, no failure alerts. Here is how to expand your own schedule, count expected runs, and reconcile them against execution records to catch silent misses.

Claude Code240scheduled tasks10cron3operations25automation107

Premium Article

An asset classification batch was set to run twice a day, morning and late afternoon, a few hundred images per pass.

What tipped me off was the backlog, not the logs. Throughput was running at roughly half of what the schedule implied. The error log was empty. No failure notification had arrived. Every run that did leave a record had exited cleanly, with nothing unusual in its output.

The afternoon run had never started at all.

A run that never starts never fails. Because it never fails, nothing that watches for failure will ever mention it. This piece is about making that blank space visible.

The Crontab Syntax Was Fine

The schedule was written like this:

30 4,16 * * *

As crontab syntax, that is unambiguously twice a day. Still, I wanted to count it myself rather than trust my reading, so I wrote a small expander that takes a cron expression and lists every moment a firing is expected inside a window.

#!/usr/bin/env python3
"""Expand a cron expression into the moments a firing is expected."""
from datetime import datetime, timedelta
 
 
def _field(spec: str, lo: int, hi: int) -> set:
    out = set()
    for part in spec.split(","):
        step = 1
        if "/" in part:
            part, s = part.split("/", 1)
            step = int(s)
        if part in ("*", ""):
            start, end = lo, hi
        elif "-" in part:
            a, b = part.split("-", 1)
            start, end = int(a), int(b)
        else:
            start = end = int(part)
            if step != 1:
                end = hi
        out |= set(range(start, end + 1, step))
    return {v for v in out if lo <= v <= hi}
 
 
def expected(cron: str, start: datetime, end: datetime):
    mi, ho, dom, mon, dow = cron.split()
    M, H = _field(mi, 0, 59), _field(ho, 0, 23)
    DOM, MON = _field(dom, 1, 31), _field(mon, 1, 12)
    DOW = {d % 7 for d in _field(dow, 0, 7)}      # Sunday is both 0 and 7
    dom_restricted = dom.strip() != "*"
    dow_restricted = dow.strip() != "*"
 
    t = start.replace(second=0, microsecond=0)
    while t <= end:
        if t.minute in M and t.hour in H and t.month in MON:
            d_ok = t.day in DOM
            w_ok = ((t.weekday() + 1) % 7) in DOW
            # Both day-of-month and day-of-week restricted means OR, not AND
            ok = (d_ok or w_ok) if (dom_restricted and dow_restricted) else (d_ok and w_ok)
            if ok:
                yield t
        t += timedelta(minutes=1)

Over seven days it expands to 14 firings. My reading of the syntax was correct, which meant the loss was happening somewhere below the syntax, in whatever actually launches the job.

That was the fork in the road. Rereading the config file would never have gotten me there. Once you have confirmed the configuration says what you think it says, the next thing to look at is not the configuration but the record of what happened.

One detail I would not have trusted without expanding it: when both day-of-month and day-of-week are restricted, cron treats them as OR. So 0 9 1 * 1 fires on the first of the month and on every Monday. Expanding September gives 09-01 (Tue) plus each Monday, five firings, which matched what I expected only after I saw it printed.

A Failure Class That Never Reaches Your Failure Log

Most monitoring around automation is shaped to catch failures. Check the exit code, forward the exception, inspect the output. All three require a process to have existed.

When the launch itself is what goes missing, none of that shape applies.

FailureShows in failure log?How you find out
Exception during processingYesAlert fires immediately
Crash or timeoutYes, via exit codeAlert fires
Preconditions unmet, did nothingNoIntended behaviour, no problem
Never launchedNoOnly by counting output volume

As an indie developer running long unattended jobs, I had built my monitoring entirely around the first two rows. There was no place in the design for a question about what did not happen.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
You will be able to prove, from records rather than from the absence of errors, that an automated job actually ran
You will be able to expand your own schedule, count expected firings, and detect the gap against real execution records with a single morning command
You will be able to catch failures where the launch itself disappears, before the missing work quietly piles up
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $15 for lifetime access
View Membership →

Related Articles

Claude Code2026-08-25
One Space in a Folder Name Turned 80 Checks Into Zero
An inspection loop reported 80 files checked and 0 readable. The files were fine. Here is how word splitting turns path fragments into real directories, measured side by side, plus the count assertion I now put in front of every delete-heavy batch.
Claude Code2026-08-04
Tightening Filesystem Isolation Separately from the Network — Collect the Paths, Then Squeeze the Write Surface
Claude Code v2.1.216 lets you control filesystem isolation independently from network isolation. Before tightening anything, I traced what a real job actually touches, split reads from writes, and measured how stable the path set is across repeated runs. The numbers changed how I wrote the allowlist.
Claude Code2026-06-19
Noticing From the Outside When a Scheduled Job Quietly Did Nothing
exit 0, but zero output. How to catch a silent no-op not from the job's own log but from an external heartbeat ledger and ground truth, written from running several sites on a nightly schedule as an indie developer.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →