自分で作った仕組みが、自分を傷つけた 4 つの記録:要約が条件を捨て、1 つの未定義が保存を止め、点検が本番の IP を閉め出された
トレカダッシュ 開発の記録 / 2026年8月〜9月
iOS アプリ「トレカダッシュ」の開発では、外から来る不具合のほかに、自分で作った仕組みや、自分でした点検が、自分に被害を出したことが何度かありました。この記事は、そのうちの 4 つの記録です。どれも、数字で見えたあとに、直しました。
数字と日付は、2026 年 8 月 28 日〜9 月 15 日の作業の記録から書いています。
1. 「15 文字程度」の指示が、応募の条件を捨てていた(9 月 14 日)
アプリは、抽選の応募の条件(フォローとリポストが必要、会員証が必要、など)を、AI に短くまとめさせて画面に出しています。表示中の抽選 671 件を、元の告知(X の投稿の本文と画像)と、AI で突き合わせて点検しました。
食い違いより、「抜け」が多く見つかりました。
| 抜けていた条件 | 件数 |
|---|---|
| リポスト | 23 |
| 会員 | 20 |
| アプリ | 13 |
| LivePocket(応募サービス) | 13 |
原因は、AI への指示文でした。要約を「15 文字程度」と指定していたので、AI は条件を 1〜2 個に削っていました。さらに、「受け取りや購入の条件は書かない」という規則を、「購入時に会員証を確認」まで広げて捨てていました。会員証は、持っていないと買えないので、応募の条件です。
文字数の制約は、AI に「どれを捨てるか」を選ばせます。捨てる規則を書くと、境界にある条件まで捨てられます。直し方は、「全部、上限は何文字」と頼み、必ず残す要素を並べることでした。点検でも、AI の判定を数えるだけで終わらず、代表例を元の画像で確かめてから直しました。AI の検品は、うるさい(誤って指摘する)ことがあるからです。
2. 1 つの値が「未定義」だと、保存が全部失敗した(8 月 28 日)
データを、まとめて書き戻す処理がありました。取得サービス(Scrape.do)の設定の記録を、全体を 1 つの塊として書き込みます。ある日、この書き込みが、毎回、こういうエラーで失敗していました。
Cannot use "undefined" as a Firestore value (found in field "domains.`www.yamada-denkiweb.com`.super")
1 つのサイトの項目に、undefined(値が定義されていない)が 1 つ混ざっていただけで、その後、どのサイトの保存も失敗し続けました。
被害は、別のサイトに出ました。「どの設定でも取得できないサイトを、6 時間休止する」という記録が、保存できなかったのです。あるサイトを、巡回のたびに 3 つの設定(1 + 10 + 25 = 36 クレジット)で叩き続け、1 日 13,183 クレジット、その日の全消費の 41% を溶かしていました。取得サービスは、日次の予算を時刻で按分するので、1 つのサイトがその日の 41% を使うと、ほかのサイトに回せる分が、その分だけ減ります。
教訓は、まとめて書き戻す形の処理は、1 つの汚れが全体の保存を壊すことです。値を書く前に、undefined を取り除く。そして、保存が失敗したら、黙らず、目立つ形で知らせます。
3. 点検のために、本番と同じ IP を閉め出された(9 月 15 日)
在庫の点検のスクリプトを、本番と同じサーバーから動かしました。通販サイト(Yahoo!ショッピング)の商品ページ 501 件を、6 並列で、素のリクエストで読みました。数分で、そのサーバーの IP アドレスごと、HTTP 489(アクセスを拒否する応答)が返ってくるようになりました。数時間たっても解けませんでした。
本番の取り込みも、在庫の再検証も、同じ IP から Yahoo! を読んでいます。点検の都合で、本番の目を潰してしまったのです。しかも、点検側は、読めなかったページを取得サービスへ回すので、そのクレジットも無駄に使い始めていました。
直し方(というより、決まりごと)は、本番と同じサーバーから通販サイトをまとめて読むときは、1 並列、1 件ごとに間を空けることです。最初に数件だけ流して、応答が 200 のままかを見てから、広げます。在庫は、まずページの中の構造化データ(在庫の有無が書かれた部分)を、少数で確かめ、全件の確認は、本番の再検証の処理に任せます。
4. 直っても鳴り続ける警告を、一晩に 4 つ作った(8 月 29 日)
異常を知らせる警告を、たくさん入れてきました。2026 年 8 月 29 日の 1 晩で、直す道があるのに鳴り続ける警告を 3 つ直し、自分で 4 つ目を作りました。4 つ目は、AI の利用残高が切れたときの印で、入金して復旧しても、24 時間、消えない作りでした。
同じ形は、前にも出ています。
- データ取得の費用の警告が、「月末には必ず 8 割を超える」。
- 取得サービスの残りの警告が、「月末には必ず残りが 2 割になる」。
- 「0 件」が正常な状態なのに、0 件で警告が鳴る。
- 取り消した定価が、翌朝、元に書き戻される往復。
消えない警告は、本物の異常を埋もれさせます。それ以来、警告を書くときは、鳴る条件と同時に消える条件を作ります。自分に聞く質問は 3 つです。
- 問題が直ったとき、この警告は、誰が消すのか。
- 月末や月初など、時間がたつだけで、必ず鳴る指標になっていないか。
- 0 件や低い値が、正常な状態ではないか。
消す人がいない警告は、作りません。成功したときに印を消す処理を、警告と同じ変更に入れます。
分かったこと
自分の道具は、自分にも効く。
- 制約は、捨てるものを選ばせる。文字数の上限を付けるなら、残すものを書く。
- まとめて書く処理は、1 つの汚れで全体が止まる。書く前に、取り除く。
- 点検は、本番の邪魔をしない。同じ IP、同じ上限を使う処理は、控えめに。
- 警告は、消える条件とセットで作る。
この話に出てくるもの
- トレカダッシュ — トレカの抽選・予約・先着の情報を集める iPhone アプリ
- 「しょうがない」を測り直したら、取得の費用は8分の1だった — 取得の費用の、別の記録
- 配備のたびに、日次の処理が丸ごと走り直していた — 自分の変更が、費用を溶かした別の例
- 本物の抽選を、静かに捨てていた 4 つの実例 — 画面に出ない失敗
ほかの記録
- X 監視の漏れ 4 つ:検索に出ない投稿、持ち主が変わるアカウント、店を探せない検索、止まった後の取り戻し — 店の X 投稿を巡回する監視で、4 店の告知が検索に 751 件取っても出なかった、登録した店が個人になっていた、店の発掘が 63 店中 11 店だった、6 日止まった後 2 時間で 2,866 件中 185 件しか読めなかった。直し方と、費用の見積もり。
- 「1 分おき」の監視は、1 件あたり 10 分に 1 回だった:速くする前に、見直しの間隔と、通知が届いた数を数えた — 先着の監視は 63 件を 1 回に 4〜9 件しか見られず、1 件あたり約 10 分に 1 回。7 日間で捕まえたのは 3 回。間隔を詰めると別の監視が遅くなり、「審査しない」ことで先着の 45% に通知が飛んでいなかった。
- 1 つの記事を商品ごとに分ける処理で起きた 3 つの取り違え:子が親になり、共有リンクが別の店を指し、名前が 2 つの商品のものだった — 分けた「子」の記事に親向けの処理をもう一度かけて、締切当日の抽選 60 件(23 店)が消えた。13 店が共有するリンクで別の店の親を引いた。2 つの商品が名乗る名前が 267 組あった。画面に何も出ないまま、本物が消える失敗の記録。
コメント
感想や、記事の間違いの指摘は、ここへ。書くには、GitHub のアカウントが要ります。
押すと、giscus(giscus.app)と GitHub に接続します。押さなければ、接続しません。詳しくはあつかいに書いています。