After tracing this by pmset -g log, log present, and SMC thermal occasions, this is the total mechanism and a layered repair. Sharing as a result of I could not discover a full writeup elsewhere.
Root trigger: DarkWake has a conservative fan coverage + an SMC-firmware-level kill swap
macOS has two “awake” states with very completely different thermal conduct:
| FullWake | DarkWake (Energy Nap) | |
|---|---|---|
| Show | On (or sleeps independently) | Pressured off |
| Fan curve | Customary — ramps freely with temp | Conservative — designed to remain quiet in a single day |
| Thermal envelope | Broad — sustained load OK, throttles CPU if wanted | Slim — at thermal degree 4, SMC firmware forces sleep |
| Meant workload | Lively consumer periods | Transient background duties (mail fetch, TM increment) |
When DarkWake workload exceeds the envelope, the SMC firmware (not user-space powerd) emits the kill sign:
DarkWake → mediaanalysisd / TM / and so on. runs → temp climbs to degree 4 →
SMC Thermal stress requested Sleep throughout energy nap →
compelled sleep (bypasses each user-space PreventUserIdleSystemSleep assertion)
This can be a firmware-level rule. caffeinate -i, app-held sleep assertions — none of them cease it.
FullWake would not have this kill swap. Similar workload → followers ramp to ~5000 RPM → temp stabilizes at degree 2–3 → sustained with out situation.
Why it began after 26.4 particularly
Each main macOS replace (and a few level releases) resets mediaanalysisd‘s evaluation state and will bundle new ML fashions that want full re-inference throughout the Pictures library:
- Video decoding (AVD {hardware} decoder)
- Neural Engine inference (face / scene / object detection)
- Metallic GPU shaders
- Heavy disk I/O throughout Pictures library
Empirically on my system:
| Metric | Pre-update | Submit-update |
|---|---|---|
mediaanalysisd log occasions/day |
~600 | ~3,800 |
mediaanalysisd: job progress occasions/day |
~0–50 | 3,000+ |
| Thermal emergencies/day | 0 | 40+ |
The post-update workload is giant sufficient {that a} typical Energy Nap DarkWake window can not full the queued job earlier than crossing thermal degree 4.
Why remote-control instruments disconnect collectively (the second-order impact)
coreaudiod holding PreventUserIdleSystemSleep retains DarkWake alive. Thermal degree 4 → compelled sleep. The compelled sleep is difficult:
TCPKeepAlive=livelywould not assist right here — the connection’s keep-alive state is within the NIC offload desk, however solely Apple-blessed providers (APNs, mDNS, and so on.) register sockets there. Consumer-space sockets from SSH, Tailscale, customized
remote-agent tooling are NOT within the offload checklist, so the compelled sleep drops them.- After sleep, these connections are lifeless. Reconnect occurs solely when one thing else wakes the Mac — usually an incidental APNs push from an unrelated service (iMessage, iCloud, Discover My), which DOES wake the host as a result of its
socket IS within the offload checklist.
That is why each distant instrument dies concurrently and reconnects on the identical second minutes later.
Diagnostic instructions
# 1. Rely thermal-emergency sleeps over the past 7 days
log present --predicate 'eventMessage CONTAINS "Thermal Emergency"
OR eventMessage CONTAINS "Thermal stress requested Sleep"'
--last 7d --info 2>/dev/null | grep -c "^2026-"
# 2. Verify mediaanalysisd is the busy course of
log present --predicate 'course of == "mediaanalysisd"
AND eventMessage CONTAINS "job progress"'
--last 24h 2>/dev/null | grep -c "^2026-"
# Baseline: 0–50. Lively backlog: 3000+.
# 3. Who's holding sleep open proper now?
pmset -g assertions | grep -E "PreventUserIdleSystemSleep|coreaudiod"
# 4. Hint thermal degree escalation
log present --predicate 'subsystem == "com.apple.thermalmonitor"
OR eventMessage CONTAINS "thermalLevel"'
--last 1h --info 2>/dev/null | grep -v ""
Repair — three ranges
Stage 1: Disable Energy Nap (minimal disruption)
sudo pmset -c powernap 0
Stops mediaanalysisd, Time Machine, iCloud sync from operating throughout DarkWake. The work is not misplaced — mediaanalysisd will catch up throughout FullWake when the fan curve can maintain the load.
Commerce-off: these duties will not run whereas the Mac is in any other case asleep. For a Mac you actively use in the course of the day, the catch-up window is adequate.
Stage 2: By no means sleep on AC (advisable for headless / remote-controlled Mac mini)
sudo pmset -c sleep 0 powernap 0 displaysleep 10
No sleep → no DarkWake → no thermal kill swap. Show nonetheless sleeps (saves the ten–30 W from the monitor). Mac mini idle FullWake ≈ 5 W; the delta vs sleep is small.
That is the cleanest repair for those who depend on always-on distant entry. It additionally by the way fixes a separate downside: most remote-control instruments can not wake a sleeping Mac through incoming visitors, as a result of their sockets aren’t registered for the
NIC keepalive offload. With sleep 0, no wake required — your message arrives, Mac is awake, processed immediately.
Stage 3: launchctl disable system/com.apple.mediaanalysisd (don’t do that)
Breaks Visible Look Up, Dwell Textual content, Pictures search, face recognition, and Apple Intelligence options. Apple respawns the service anyway. Skip.
Lengthy-term: monitor when the backlog clears, then revert
If you don’t need sleep 0 completely, arrange a each day verify through launchd that counts mediaanalysisd job progress occasions. When rely is < 200/day for 3 consecutive days, the backlog is completed and you may revert.
~/scripts/check-mediaanalysis-backlog.sh:
#!/bin/bash
set -uo pipefail
LOG_DIR="$HOME/logs"
STATE_FILE="$LOG_DIR/backlog-clear-streak"
WATCH_LOG="$LOG_DIR/backlog-watch.log"
PROGRESS_THRESHOLD=200
REQUIRED_STREAK_DAYS=3
mkdir -p "$LOG_DIR"
log() { printf '[%s] %sn' "$(date '+%Y-%m-%d %H:%M:%S %Z')" "$*" >> "$WATCH_LOG"; }
progress=$(/usr/bin/log present
--predicate 'course of == "mediaanalysisd" AND eventMessage CONTAINS "job progress"'
--last 24h 2>/dev/null | grep -cE '^2026-' || true)
log "progress_24h=${progress} (threshold: < ${PROGRESS_THRESHOLD})"
if [[ "$progress" -lt "$PROGRESS_THRESHOLD" ]]; then
streak=$(cat "$STATE_FILE" 2>/dev/null || echo 0)
streak=$((streak + 1))
echo "$streak" > "$STATE_FILE"
log "BACKLOG CLEAR — streak ${streak}/${REQUIRED_STREAK_DAYS}"
if (( streak >= REQUIRED_STREAK_DAYS )); then
log "REVERT TRIGGER"
/usr/bin/osascript -e 'show notification "mediaanalysisd backlog cleared — revert pmset" with title "Mac mini" sound identify "Glass"'
echo 0 > "$STATE_FILE"
fi
else
echo 0 > "$STATE_FILE"
fi
~/Library/LaunchAgents/com.YOU.check-mediaanalysis-backlog.plist:
Label com.YOU.check-mediaanalysis-backlog
ProgramArguments
/bin/bash
/Customers/YOU/scripts/check-mediaanalysis-backlog.sh
StartCalendarInterval
Hour 22 Minute 0
Load:
launchctl bootstrap "gui/$(id -u)" ~/Library/LaunchAgents/com.YOU.check-mediaanalysis-backlog.plist
When the notification fires, revert (use your pre-override values from pmset -g customized snapshot):
sudo pmset -c sleep 1 powernap 1
Why “reset SMC” and different generic recommendation falls quick
- Reset SMC — would not assist as a result of the workload inflicting overheat is software program, not firmware
- Wait it out — true however takes 1–4 weeks for giant Pictures libraries
killall mediaanalysisd— Apple respawns; you may be preventing it indefinitely- Disable Energy Nap alone — addresses mediaanalysisd, however would not tackle the identical thermal entice when a distant consumer sends a heavy command (which additionally lands in DarkWake with out HID enter)
Stage 2 (sleep 0) addresses each the OS-induced backlog AND user-induced distant workload, which is why it is the best repair for headless / remote-controlled Mac minis.
