Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】The Upload Succeeded, the Record Did Not

2026年08月25日に「Dev.to」が公開したITニュース「The Upload Succeeded, the Record Did Not」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

YouTube動画のアップロードで、動画が成功しても検証失敗でローカル記録が残らず、再実行すると同じ動画が重複する問題があった。原因は、動画アップロード成功と記録の間の処理中断。解決策として、検証前にまず動画IDを仮記録し、後に検証結果で更新する仕組みを導入。これにより、重複アップロードを防ぎ、処理中断時の状態も明確になった。

出典: The Upload Succeeded, the Record Did Not | Dev.to公開日:

ITニュース解説

あるシステムでYouTubeに動画をアップロードする処理を構築した際、予期せぬ問題に直面した。その処理は、まず動画のアップロードを開始し、ファイルをYouTubeに送信して、動画の識別子(ID)を受け取る。次に、アップロードされた動画が正しく公開され、内容や設定が意図通りに反映されているかを確認し、最後にその動画がアップロード済みであることを示す記録をローカルのファイルに残すという一連の流れで構成されていた。このうち、最後の二つのステップ、「アップロード内容の確認」と「ローカル記録の書き込み」の間に問題が潜んでいたのである。

具体的に何が起こったのかというと、動画ファイルのアップロード自体はYouTube側で成功し、動画IDも発行されていた。つまり、YouTube上にはすでに動画が存在する状態だった。しかし、その後の「アップロード内容の確認」ステップで何らかのエラーが発生すると、そのエラーが処理全体に伝わり、動画がアップロード済みであることを示すローカルの記録ファイル(仮に「upload.json」と呼ぶ)が、全く書き込まれないまま処理が終了してしまった。

この状態は非常に厄介だった。システムから見ると、ローカルに「この動画はアップロード済みである」という情報がないため、次に同じ動画をアップロードしようとすると、システムは「まだアップロードされていない」と判断してしまう。結果として、同じ動画がYouTubeに二重にアップロードされてしまう事態が発生したのである。これは、YouTubeに無駄な動画を増やし、管理を複雑にする大きな問題だった。

なぜこのような問題が発生したのかを詳しく調べると、プログラムのコードの中に書かれた説明書き(ドキュメント)に「リトライしても動画は重複しない」という記述があったことが原因の一つとして挙げられる。しかし、この説明は「低レベルなファイル送信中に一時的なネットワークエラーなどで途切れた場合、同じアップロードセッションを再利用して続きから再開する」という限定的な状況にのみ当てはまるものだった。今回のケースのように、一度アップロードが完了し、その後の確認ステップでエラーが発生して、外部からプログラム全体を再実行する場合の「リトライ」は、まったく異なる処理経路を通るため、この安全対策の範囲外だったのだ。つまり、「リトライ」という言葉が指す意味が、ドキュメントの記述と実際のプログラムの動作で異なっていたことが誤解を生んでいた。

さらに調査を進める中で、まったく同じ根本原因によるバグが、すでに稼働中の別の動画アップロード経路でも発生していることが判明した。以前から使われていた別の管理ツールを通じてアップロードされた動画が5本あり、それらについてもローカルの記録ファイル「upload.json」が作成されていなかったのだ。このため、新しく作成した重複防止の仕組みは、これらの既存動画がすでにYouTubeに存在することを認識できず、もしそれらの動画を新しいアップロード経路で処理しようとすれば、やはり重複アップロードが発生してしまう危険性があった。この問題は、重複防止のロジック自体が間違っているのではなく、複数の異なる処理経路が存在する場合に、それぞれの経路が同じ情報(ここではローカルの記録ファイル)をきちんと更新し、共有する仕組みが欠けていたことにあった。

このような重要なバグがなぜ開発段階で見つけられなかったのかも検討された。結果として、関連するすべての単体テストは正常にパスしていたことが分かった。動画が正しくアップロードされるか、ローカルに記録ファイルがない場合にどう振る舞うか、公開設定が正しく適用されるか、重複防止の仕組みが機能するか、そして確認ステップでエラーが発生した場合に正しく例外が投げられるか、といった点はすべてテストで確認されており、問題なく動作していた。しかし、テストが確認していなかったのは「例外が発生した後、ディスク上にどのような状態が残るのか」という点だった。テストは通常、関数が何を返すか、どんなエラーを出すかに焦点を当てるが、エラーが発生した後のファイルシステムの状態のような「残存状態」については、見過ごされがちなのである。このバグはまさに、そうした残存状態が引き起こす問題だった。

この問題の解決策は、記録ファイルを書き込むタイミングを変更することだった。新しい処理では、動画IDがYouTubeから返ってきた瞬間、つまりファイルのアップロードが成功した直後で、かつ「アップロード内容の確認」が始まる前に、まずローカルの「upload.json」ファイルに記録を作成するようにした。この記録には、「この動画は存在するが、まだ確認は完了していない」という意味で「検証済み: false」というフラグを付けておく。その後、「アップロード内容の確認」処理が実行され、それが成功すれば、記録は「検証済み: true」に更新される。もし確認中にエラーが発生したり、システムが停止したりしても、ローカルには「YouTubeには動画があるが、まだ最終確認が終わっていない」という情報が残る。

これにより、同じ動画のアップロードコマンドを再実行した場合の挙動も改善された。システムはまずローカルの記録を確認し、「検証済み: false」の記録があれば、新しいアップロードを開始するのではなく、既存の動画IDを使って中断されていた確認処理を再開するように変更された。これにより、無駄な重複アップロードは防止され、中断された処理を効率的に再開できるようになった。

すでにYouTubeにアップロードされており、記録ファイルがない状態だった過去の5本の動画については、YouTubeのAPIを通じて実際の動画IDや公開状態などの情報を取得し、それに基づいて手動で「upload.json」のエントリを作成し、ローカルの記録を最新の状態に更新した。これは、YouTube側から必要な情報が取得できたからこそ可能だった対処方法である。

この経験から学べる教訓は、他の多くのシステムにも応用できる。リモートのシステム(YouTubeのような外部サービス)で何らかのリソース(動画、支払い承認、クラウドサーバーなど)を作成し、その後そのリソースの状態を確認するという一連の操作には、必ず**「リモートでリソースが作成された瞬間」と「その事実がローカルのシステムに記録される瞬間」との間に「窓」のような時間的な隙間が存在する**。この「窓」の中で処理が中断してしまうと、「リソースは作成されたが、その後の確認ステップだけが失敗した」のか、あるいは「リソース自体が全く作成されなかった」のかを、ローカルのシステムからは区別できなくなる。この区別ができないと、「リトライ」という操作が、意図せず「重複作成」を引き起こしてしまう可能性があるのだ。

この問題を防ぐための基本的なルールは、リモートでリソースが作成され、その識別子(ID)を受け取った瞬間に、まずその事実をローカルに記録することである。その後の確認や追加処理の前に、まず記録を完了させる。この記録は、「完了済み」だけでなく、「発生したが未確認」という中間状態も表現できる必要がある。なぜなら、その中間状態こそが、「窓」が開いている間のシステムの実際の状態だからだ。

そして、開発者が常に問いかけるべき診断的な質問は、「このプログラムが任意の行で突然停止した場合、同じ処理を再実行すると、以前と同じ結果が得られるか?」というものである。特に、リモートでの書き込みが成功した行から、その事実がローカルに記録されるまでのコードの範囲について、この質問を一つ一つの行に対して厳密に自問自答することが重要だ。その間のコードが長ければ長いほど、途中で処理が停止する可能性が高まり、問題が発生しやすくなる。

もう一つ重要な教訓は、もし複数の異なるプログラムの実行経路が、同じ種類のリソースを作成する可能性がある場合、それらすべての経路が同じ方法でローカルの記録管理(帳簿付け)を行う必要があるということだ。ある一つの経路だけを念頭に置いて重複防止の仕組みを構築すると、他の経路で作成されたリソースについては何も知ることができず、結果として重複チェックが機能しなくなる。今回のケースで、既存の5本の動画が新しい重複防止機能に認識されなかったのは、まさにこの理由によるものだった。テストは、自分が何をチェックしているかについては正しかったが、システム全体として「何が壊れる可能性があるか」という点を見落としていたのである。

関連コンテンツ

関連IT用語