Skip to content

Build1 publisher2 min readPublished

A Claude Code skill updater failed three straight Sundays while its audit note still read "exit 0"

One developer's weekly Claude Code skill update failed on 6, 13 and 20 September despite three layered fixes and an audit note reading "exit 0". The script caught and logged every failure correctly, but the log had no reader until the author opened it after the third one.

The Engineer · Build desk

Illustration accompanying A Claude Code skill updater failed three straight Sundays while its audit note still read "exit 0"

What happened

  • A developer's launchd job runs npx skills@latest update -g every Sunday at 4:40 to keep their Claude Code skills current.
  • The script carries three fixes: a gh token lifting GitHub's limit from 60 to 5,000 requests an hour, a 600-second timeout, and a STAMP file touched only on success.
  • A code comment records that an audit on 8 August 2026 measured a run at 4 minutes 00 seconds with exit 0.
  • The error log shows the job failing on 6, 13 and 20 September, all Sundays, each time with the same "timeout or error" line.
  • The author had assumed the job was fixed and found the three failures only after opening the actual logs.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • decision A dated exit-0 comment certifies one run; keeping a weekly job healthy takes a separate check on STAMP's age that alerts once the last success is more than a week old.
  • constraint One fixed message covers both timeout and error, and no exit code is kept, so the owner has to reconstruct which defense gave way from timestamps alone.
  • exposure If gh ever returns no token, the job drops back to GitHub's 60-an-hour anonymous limit and the published code writes nothing to the log to say so.

The timestamps say more than the error message does. The plist fires at 4:40 [1]. The 6 September failure was logged at 04:40:38 and the 20 September one at 04:41:35 [10]. If those runs started on schedule, they failed about 38 and 95 seconds in [1]. The cap is 600 seconds [4]. On those two Sundays the timeout cannot have fired. Both runs also ended sooner than the 4-minute run the August audit measured [1].

The 13 September entry is different. It landed at 05:27:06, 47 minutes after the scheduled start and longer than the whole 10-minute cap [2]. That run either began late or spent its time outside the capped command [2].

Between the failure lines, stderr caught npx reporting that [email protected], and later [email protected], "was not found and will be installed" [12]. The author attributes those lines to npx's own bootstrap [12]. Because the script asks for `skills@latest`, a new CLI release means a package download before any update work starts. In the script, that download runs inside the same `gtimeout 600` budget as the update itself [4]. The logs quoted in the post do not by themselves establish a root cause.

According to the code comments the developer published on dev.to, this is the third stretch of failure on record [3]. A 2026-06-11 audit found that the old script touched STAMP even when the update failed, so updates kept failing silently whenever the network misbehaved [6]. Later, a 45-second timeout expired on every run as skills piled up. It produced a 5,833-line failure log and not one successful update [5]. The 2026-08-08 audit then measured a clean 4m00s run [7].

The STAMP change was good engineering. Touching the success marker only on success, and writing the failure reason to skills-update.err, is why September left any trace at all [6] [8]. launchd, for its part, never missed a Sunday [8].

The 600-second cap was set against one measurement. The audited run on 8 August used 240 of its 600 seconds, or 40% [4]. The author wrote that runs stalled more often as the skill count grew [13].

The author drew the lesson from the comments themselves. "But those are only facts verified at that point in time. They don't prove the job keeps working afterward," the author wrote [14]. The script already produces the signal a check would need: STAMP's modification time is the time of the last successful update [6].

What to watch

  • Whether the author's diagnosis ties the September failures to npx's bootstrap download of new skills CLI versions or to the GitHub API calls themselves.
  • Whether the next fix records the exit status or adds a staleness alert on STAMP, the first change aimed at getting a failure in front of a person.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories