Claude Code can fall back to a second model when the primary is overloaded, and a wall-clock watchdog kills a hung headless run before it eats your morning. Today's lesson closes the loop you accepted on 06-09 but never wired in — and it's the direct cause of the 🚨 pile in your Inbox.
Scroll your Today list: 'PDB plan-day failed 2026-06-25', 'PDB weekly-review failed 2026-06-21', 'Learning email failed' four times, 'Language pre-render failed' five times. These are headless runs dying on overload with no fallback, and hanging with no watchdog. You ACCEPTED fallback chains on 06-09 — it just never made it into settings.json or the cron flags. That gap is the backlog.
When you run a job headless (`claude -p ...` from a LaunchAgent), the model can come back 'overloaded' or 'unavailable' — a 529/503 from the server. With one model named, that's the end of the run: it errors, the LaunchAgent logs a non-zero exit, and you get a 🚨 task (if you're lucky) or silence (if you're not). `--fallback-model` lets you name a backup that's tried automatically when the primary fails over — you can chain up to three.
But a fallback only solves 'the server said no.' It does NOT solve 'the run hung for 34 minutes' — which actually happened to plan-day on 5/30. That's a different failure, and the fix is a wall-clock watchdog: wrap the whole command in `timeout` so it's killed at a hard ceiling. Your own CLAUDE.md automation-hygiene rule is blunt about this: 'every long job has a watchdog you've proved kills,' and 'an unverified watchdog is decorative.'
Both belong on the same jobs: `run_plan_day.sh`, `run_weekly_review.sh`, and the `language_lesson.py` / `learning_lesson.py` LaunchAgents. The 🚨 backlog is the symptom of neither being wired — a perfect case study for the day you're about to leave the system unattended for two weeks.
The two-line hardening — a fallback chain plus a timeout watchdog around a headless run:
# BEFORE — one model, no ceiling. Overload or hang = failure.
claude -p "$(cat plan_day_prompt.txt)"
# AFTER — fallback chain + 25-min wall-clock watchdog
timeout --signal=TERM --kill-after=30s 25m \
claude -p "$(cat plan_day_prompt.txt)" \
--model claude-opus-4-8 \
--fallback-model claude-sonnet-4-6 \
|| /usr/bin/python3 ~/Claude/PDB/scripts/notify_fail.py "plan-day"
A fallback model saves you from 'the server said no'; a watchdog saves you from 'the run never came back.' Critical jobs need both — and a failure that doesn't surface as a 🚨 task isn't handled, it's hidden.