この記事は、次の記事の続き記事です
よかったらご参照ください。
- FastAPIでWebSocketを使っていてUvicornとWebSocketsライブラリの食い合わせでエラーが出た時の話 | よそなかの 人生は調べもの
- Perplxityの生回答 @ 2026-Feb-07 時点の情報
最初の印象
まず単純に「スゲーナ」と。何となくわかっていたことだが、エラーに対する対処・調査はもはやLLMっていうかこの際AI Agentと呼ぼうか。個人的にはCometブラウザを使い続けていて、PerplexityはCometブラウザ経由で使っているが、この手のAI Agentにはもはや勝てないなと思う。
実際とりあえずでその対処をしてみて動いた。その時点で、ああ、これはすごいと。マジかよと。何度も体験しているAIの驚きだが、ことプログラミングのトラブルについて、AI Agentのあたり率はやばい。誰がそうしたんだ、、、!?
プログラミングのトラブルはとりあえずチャッピー君に聞いておけ
この知見は共有しておきたい。プログラミングでトラブルを起こしたとき、ベテランに聞けたらとても良いのだが、それができないとき(あるいはそのベテランとの相性が悪いとき)には、AI Agentは驚くほど役に立つ。自分で調べたり、原因追及するのはそのあとでもよい気がする。
もう少し言おう。この手のバグは一過性だったり、適用される状況が限定的だったり、情報が古くて探しても意味が無かったり、、、、この道15年のベテラン(笑)として言わせてほしい。対処するとき、その多くはただただ無駄な時間だ。将来にわたっても「思い出以上の価値は生み出されない」無駄な時間だと言い切りたい。とっととググれの時代から、とっとと、、、えっと、、、パプれ????チャピれ???はい。GPT先生に聞く時代だ。あー、GoogleもAI Agent乗ってたか。それでもいいかも。新時代のGoogle先生に聞いていこう。
なお、MSのAI Agentはなぜかどいつも(Copilot)こいつも(Edge Copilot)、なんならあいつも(Bing Copilot)体感ゴミな模様(@2026-Feb)。なんでや。
自分が作ったバグで、真の原因を探しているときや、秘匿された情報が存在してる場合など(プロプラなコードやMSDNにありがち)は若干事情が変わる、、、のだが、一次情報として、現在の原因を探すとき、特に「外部に情報を求めるとき」に、AI Agentに頼らないのは、「楽しい」以外のメリットがもはやない気がする。うん。これだけ書きたかった。
、、、と、ここまで思って(後だしで書いているが、実際最初、わりと素直にそう思った)はっとした。
「自分が未知のエラーに対処する力はつける必要があるかも」
と。
というわけで、Perplexityの回答を分析してみることにした
そうすることで、おそらくだが、「どういう戦略で今後調べるのか」のヒントが見えてくる、、、気がした
まず気になるのは
- 検索ストラテジ
- そもそもどういう情報元を参照したか
- 得られた結果をどう分析したか
これらを知っておきたいかなと思う。
検索ワードはMarkdownに書き出されないのか、、、
2回分の問い合わせでの検索ワードは次の通りであった
- “WebSocketProtocol” object has no attribute ‘transfer_data_task’
- FastAPI WebSocket WebSocketProtocol transfer_data_task Did you mean transfer_data_exc
- websockets 12 transfer_data_task removed
- uvicorn 0.40.0 websockets 16.0 WebSocketProtocol transfer_data_task
- fastapi 0.128.1 websocket AttributeError transfer_data_task
- websockets 16 transfer_data_task removed
- uvicorn websockets legacy sans-io
2回目はURL参照が追加されている
これらを見て気づくこととしては
- 一度目の検索では、シンプルにエラーメッセージから得られる情報を検索している
- 「Removed」というキーワードを「Did you mean?」というあたりから得ているのだろうと推測されるが
逆にこの検索ワード、出せるものか???テクい - 2度目の検索は、1度目の検索結果を精査しないと分からないような要点を絞った検索になっていると感じる
- とくに関数名(transfer_data_task)と追加ワードで絞り込むあたりかなり思いつかない
いや、自分ぐらいのベテラン(笑)だからだめで、トップ層はあるいは、、、たどり着けるのかも
検索結果を見る
https://github.com/python-websockets/websockets/issues/1396
この情報がPerplexityの回答で最も重要な原因の看破につながっている
このエラーは、
websocketsライブラリ側のバグ(特定条件でtransfer_data_taskがセットされる前にclose()が呼ばれる)で、FastAPI/Starlette/uvicorn を使った WebSocket でも報告されています。
このページについては、スタックトレースがそのまま乗っていることもあって、自力でも到達していた。ただ、英語過ぎて読めていなかった。改めてブラウザの翻訳機能を使って次のように書かれていた。
これは、uvicornがWebSocketを埋め込む方法に関係しています。このユースケースに適したAPI、つまりSans-I/O実装を提供する前に統合されました。これはプライベートAPIを使用して行われており、WebSocketが依存するロジックと不変条件を完全には尊重していません。これを修正するのは困難であり、あまり意味がありません。
現在、埋め込み用の優れた API が存在しており、uvicorn に採用される予定です: Kludex/uvicorn#1908
それは本当に適切な修正です。
原文
Member
This has to do with how uvicorn embeds websockets. It was integrated before I provided a good API for that use case — namely the Sans-I/O implementation. It’s done by using private APIs and it doesn’t respect perfectly the logic & invariants that websockets relies on. This is hard and not very valuable to fix.
Now the good API for embedding exists and it should be adopted in uvicorn: Kludex/uvicorn#1908
That’s the proper fix really.
初見のときのことを思い出すと、次のように理解していた。
- Sans-I/Oというのがあるらしいということ
- 関係のあるチケットがあること (Kludex/uvicorn#1908のこと)
これだけだったが、改めて読んでみて、解決してみて、読み取れる情報が増えているのを感じる。
- Sans-I/O とは WebSocketsライブラリの実装の何かの名前である
- uvicornがWebSocketを埋め込む方法に関連している (This has to do with how uvicorn embeds websockets.)
- このチケットは よく見たら uvicorn のものである
- 「採用予定である」
- チケット全体を見直すと「言及」されたチケットが結構ある
https://github.com/Kludex/uvicorn/issues/1908
このページについては、一応開いたが関係がわからず、というかシンプルに読めず、なんなら最初は翻訳機能も利用していなかったのでさっぱり関係性を理解せずにスルーしていた。
というか自分の英語読解の能力というか、その低下というかなんというか。その、えっとー、愚痴っぽいのでやめておこう。
長いので、これが直接の対処法が書かれていると気づけるのだろうか、、、というか、解決したからわかるのだが、自分はずーっとFastAPIの実装の問題だと思っていたが、Uvicorn、WebSocketsの問題であったのだ。
えー???
対処法が最後に書かれていた。
(略)
このプロトコルを使用するには、設定する必要があります
--ws websockets-sansio。
自分が改めて解決後に翻訳を読んでみて気づいた点を記載しておく
- Perplxityの回答にあった「
--ws websockets-sansio」の対処法はたしかにここに書かれていた - kludex/uvicorn は Cometの自動翻訳では「クルーデックス / ウビコーン」である
- このチケットはシンプルにバグチケットであり、対処法が書かれたものではないし、質問でもない
他のエラー報告ページ
全部軽く目を通したら次の気づきがあった
- WebSocketとその実装に関連する問題であるということを自分が検索してなくて情報に当たれてなかった
- あとは、日本語の情報ばかりに頼っていて、英語を読解・機械翻訳すらしていなかった
とりあえず翻訳してみて、そこから問題のコアを読み取るというのが戦略として採用できそう - その他検索結果自体は、今回の問題とは関係のないものが多かった
https://uvicorn.dev/concepts/websockets/#websockets-sansio-protocol
Uvicornのパラメータが対処法だったということで改めてドキュメントを見たら、ちゃんと更新してあった
WebSockets SansIO Protocol¶
Since
websocketsdeprecated the API Uvicorn uses to run the previous protocol, we had to create this new protocol that uses thewebsocketsSansIO API.You can choose this protocol by setting the
--wsoption towebsockets-sansio.
うーん、、、!
日本語情報
これらの情報について、日本語の情報はあるか、ないか?
うーん、、、検索が上手くなくて、見つけられない
- FastAPI WebSocket 切れる
- WebSocket つながらない
Issue Ticketを見る限り、2025年7月にIssue Closedになっているので、本当に最新バージョンでしか出ない問題っぽい感じはする。
2025年7月から現在(2026年2月)に至るまで、試した人がいないか、試していても共有していないか、
あるいはAI Agentに消された、、、!?
分析
どうやったらPerplexityの回答を導けるかについては、ちょっと実のところ想像できない。
- なぜ WebSocketsにあったTicketと、UvicornにあったTicketから、
--ws websocket-sansioまでたどり着けたのか - それがバージョン問題であるとどうやって看破したのか
- というかFastAPIの問題ではなく、WebSocketsとUvicornのバージョンの食い合わせの問題だとなぜわかったのか
一応当のツール自身に開示させてみた
ツールを使って情報を収集し、ステップバイステップで分析しました。以下に思考経路を時系列で開示します。
初期エラー分析(1回目ツールコール)
エラーメッセージ
"AttributeError: 'WebSocketProtocol' object has no attribute 'transfer_data_task'. Did you mean: 'transfer_data_exc'?"をキーワード検索。[github]
- GitHub issue(python-websockets/websockets #1396)で同一エラー発見。
原因:websocketslegacy 実装のバグ。close()時にself.transfer_data_task.cancel()を呼ぶが、タスクが未作成で AttributeError。[github]- uvicorn issue でも関連報告(#1908)。WebSocket 実装を “legacy” から “Sans-I/O” に移行中と判明。[github]
環境情報確認後(2回目ツールコール)
あなたの pip freeze を基にバージョン特化検索(uvicorn 0.40.0, websockets 16.0)。
- 最新版でも legacy 問題が残る報告あり。[github]
- uvicorn の WebSocket 実装オプション確認(
--ws)。websockets-sansioが Sans-IO で安定。[uvicorn]詳細確認(3回目ツールコール)
uvicorn 公式ドキュメント fetch。
/concepts/websockets/:--ws websockets(legacy, デフォルト),--ws websockets-sansio(Sans-IO, 推奨),--ws wsprotoを明記。legacy は非推奨でバグ多め。/release-notes/: 0.35.0 で Sans-IO 追加。以降バージョンで改善。[github]結論導出の論理
- エラー根本原因: websockets legacy の private API 依存(transfer_data_task)。[github]
- あなたの環境: uvicorn 0.40.0 は Sans-IO 対応済み →
--ws websockets-sansioで回避可能。[github]- 優先度: コード変更不要・コマンド1つで解決。Gunicorn 対応も考慮(あなたの freeze に gunicorn あり)。
- 検証性: 公式ドキュメント直結で信頼性高く、再現条件(高速切断)とも一致。[github]
この経路で、ツール結果をクロス検証し、具体的なコマンドを提案しました。追加質問があればどうぞ。
この問題の結論を得るとき、2つの英語のチケットが情報元として有用であり、しっかり関連性を理解できていたかが今回の問題のカギだったように見受けられる。
総括
まず、すでに書いたし、何度でも主張したいが、ことプログラミング外部情報に頼るとき、最初の選択肢としてAI Agentを頼るのは思ったより現実的な選択肢である。他の問題もそうしろというわけではないし、常にそうしろというわけでもない。常に当たる、よく当たるとも言わない。過去にははずれも多かった。けれど、頼らないよりはるかに助けになるのは間違いない。特に、今回のような「結構読み解かないと当たらないような情報」を理解するうえでかなり助けになることがわかる。
AI Agentじゃない自分の対処法として
これについては、ここまでに書いたことも踏まえて・繰り返して考えると、、、AI Agentを使わないとして
- 英語情報を見るとき、とりあえず翻訳しちゃって、それから原文を交えて精査するのは有利そう
- 問題を疑うとき、登場人物としてのインフラ(今回の場合Uvicorn, WebSocketsライブラリ)を意識するのは結構有意義な可能性がありそう。
- 何らかのAPI不整合が起こったとき、バージョン問題に遭遇している可能性を疑うのは有意義そう。
あとは、ちょっとどうしたらよいかわからない気づきについての課題として、個人的に残る思いとしては
- 今回のように情報を精査すればわかりうる場合は、どうアプローチするのが良いか
- 特に今回チケットやバグレポートのような、つながりのわかりづらい情報で、そこから情報をしっかりと取りこぼさないために意識できることはもっとあるのではないか
- 検索キーワードの選定。初期の検索ワードで選ぶとよい言葉のパターンは?
これらはまだ私の中では課題として残りそうである。
最後に雑文等
- 同様のAI Agentを作ろうと想像したとき、ストラテジ・プロンプトがマジで謎
- この手の「トラブルシュートのベンチマーク」ってないんだろうか?あったら面白い。ありそうな気はするけどな。
- 隔世の感。10年前なら多分日本誤情報もあふれてそう、、、って思っちゃった。自分の老化だな。
お疲れ様でした
見ていただき感謝する。
あなたに何かしら得るものがあれば幸いである。