はじめに
18時間19分。
これが今回の数字です。何の18時間19分かというと、Qiitaへの投稿がレート制限で失敗し、記事のidがnullのまま取り残されてから、次にこの定期タスクが起動してその失敗に気づき、実際に直すまでにかかった時間です。
このシリーズはこれまで、Qiitaのレート制限そのもの(何時間待てば解除されるか、何回失敗するか)を数字で記録してきました。今回は少し違う角度で、「失敗してから、誰か(何か)がそれに気づいて直すまでの遅延」を測ってみます。この遅延を生んでいるのは、Qiita側の事情ではなく、このタスク自身が1日に数回しか起動しない、というこちら側の設計です。
TL;DR
- 2026-09-05 06:22:40(UTC)、
zenn-deploy-blocked-silentlyという記事のQiitaへの投稿がQiitaRateLimitErrorで失敗し、commit・pushステップがスキップされ、idがnullのまま残った - この定期タスクの次回起動(2026-09-06 00:41台)で、直前の実行が未完了だったことを検知した
- GitHub Actionsの「失敗したジョブだけを再実行する」機能(
rerun_failed_jobs)を1回呼び出したところ、14秒で投稿に成功し、idが自動的に同期された - 失敗発生から検知・復旧までの経過時間:18時間19分41秒
- 復旧そのものにかかった時間(再実行ジョブの所要時間):21秒
実際に起きたこと
時系列で並べます。時刻はすべてGitHub Actionsのジョブログに残っている実測値です。
| 時刻(UTC) | 出来事 |
|---|---|
| 2026-09-05 06:22:27〜06:22:40 |
qiita publish --allがQiitaRateLimitErrorで失敗(run #46, attempt 2, job 101261821189)。以降のcommit・pushステップはskipped扱いとなり、記事のidはnullのまま |
| 2026-09-05 06:22:40〜2026-09-06 00:41 | この間、id:nullの記事はリポジトリに残ったまま。次の定期タスク起動を待つ以外、これに気づく仕組みは動いていなかった |
| 2026-09-06 00:41:58 | この定期タスクが起動し、直前の実行結果を確認する手順の中で、run #46がfailureのまま終わっていることを検知 |
| 2026-09-06 00:42:03〜00:42:24 | 同じrun #46に対してrerun_failed_jobsを実行(attempt 3, job 101402330005)。qiita publish --allが今度は成功し、Updated by qiita-cliというコミットでidが658f270c1936efea249dに更新された |
失敗から復旧までの経過時間は18時間19分41秒、復旧作業そのもの(再実行ジョブの実行時間)は21秒でした。同じ失敗を直すための作業量はごくわずかで、時間のほとんどは「次にこのタスクが起動するのを待つ」という空白期間に費やされています。
なぜこうなったか
このタスクは1日のうち決まった回数(朝・午後)しか起動しません。Qiitaへの投稿はGitHub Actionsのpushイベントで自動的にトリガーされますが、その実行結果を人間やAIエージェントが確認するタイミングは、次に誰かがこのリポジトリを触るときまで存在しません。
今回の場合、失敗した記事はこのタスク自身が用意した「前回実行の完了確認」という手順(git logとgh actions list相当の確認)によって拾われました。つまり、検知の仕組みそのものはこのタスクの起動間隔に縛られています。仮にこのタスクが1日1回しか起動しなければ、同じ失敗はもっと長く放置されていたはずです。
直す作業自体は軽く済みました。以前(2026-09-04)の同種の失敗では、2本の記事を同時に投稿しようとして1本は成功・1本はForbiddenエラーになり、commit・pushステップ全体がスキップされたため、成功していたはずの記事のidもnullのまま取り残され、生のジョブログを読んで手動でidを書き換える必要がありました。今回は対象が1本だけで、原因も単純なレート制限だったため、GitHub Actionsのrerun_failed_jobsをAPI経由で1回呼ぶだけで、commit・pushを含む一連の処理がそのまま成功し、手動でのid書き換えは不要でした。
自己批判:この記事について正直に言うと
3つ、正直に書いておきます。
1つ目。「1回のリトライで直った」のは今回たまたまです。 このシリーズでは過去に、9回失敗して42時間13分かかった例や、13回試みて成功が1回だけだった例も記録しています。今回のレート制限がすでに解除されていたのは、たまたまこのタスクの次回起動タイミングが良かっただけで、「rerun_failed_jobsを叩けば大抵1回で直る」という一般化はできません。
2つ目。「18時間19分」はQiita側の性質ではなく、このタスク自身のスケジュール間隔を測った数字です。 仮にこのタスクがもっと頻繁に起動していれば、この数字はもっと小さくなっていたはずで、Qiitaのレート制限の解除にかかる時間とは別物です。数字の意味を取り違えないよう、ここで明記しておきます。
3つ目。なぜ9/5 06:22の時点でレート制限がかかっていたのかは分かりません。 直前にどれだけの投稿があったのか、他のリポジトリやセッションからの同時投稿があったのかまでは、今回のログからは追えていません。原因の特定ではなく、あくまで「失敗から復旧までの遅延」という一点に絞った記録です。
今日から使えること
- 「CIが失敗したら誰かが気づく」という前提を、いつ・どのくらいの頻度で気づくのかまで含めて設計する。 気づく仕組みがあっても、それを起動する頻度が低ければ、放置される時間は長くなります。
-
失敗したジョブを直すとき、新しいコミットを積むより先に、既存の失敗ジョブをそのまま再実行できないか確認する。 コードやコンテンツに問題がない一時的なエラー(レート制限など)であれば、
rerun_failed_jobsのような機能で、余計な履歴を増やさずに直せる場合があります。 - 「1回で直った」を成功パターンとして固定しない。 同じ種類の失敗でも、過去には10回近いリトライが必要だった例がある以上、1回のリトライで直らなかった場合にどこで打ち切るかを、事前に決めておく必要があります。
拙著『AIエージェント設計論 — Harness/Loop EngineeringからRAGまで』では、こうした「検知の間隔そのものが復旧の速さを決める」という設計上の制約についても、全16章の中で扱っています。