🐛

Net::ProtocRetryErrorのエラーをなくすためにnet-httpのgemを追加する

2023/08/06に公開

前提

  • Ruby:2.7.1
  • rails:6.0.5

結論から

Gemfileに以下を追加する

gem 'net-http'

問題

rails s時などの立ち上げ時に以下のエラー

app_1      | /usr/local/lib/ruby/2.7.0/net/protocol.rb:66: warning: already initialized constant Net::ProtocRetryError
app_1      | /usr/local/lib/ruby/gems/2.7.0/gems/net-protocol-0.2.1/lib/net/protocol.rb:68: warning: previous definition of ProtocRetryError was here
app_1      | /usr/local/lib/ruby/2.7.0/net/protocol.rb:206: warning: already initialized constant Net::BufferedIO::BUFSIZE
app_1      | /usr/local/lib/ruby/gems/2.7.0/gems/net-protocol-0.2.1/lib/net/protocol.rb:214: warning: previous definition of BUFSIZE was here
app_1      | /usr/local/lib/ruby/2.7.0/net/protocol.rb:503: warning: already initialized constant Net::NetPrivate::Socket
app_1      | /usr/local/lib/ruby/gems/2.7.0/gems/net-protocol-0.2.1/lib/net/protocol.rb:541: warning: previous definition of Socket was here

問題が生じる理由

ref: https://github.com/ruby/net-imap/issues/16#issuecomment-803086765

  • When the faraday-net_http gem is required, it then requires net/http.
  • Then the stdlib version of net/http is loaded, since bundler doesn't know net-http is a gem dependency, so it doesn't add the gemified version to to the $LOAD_PATH.
  • Then the stdlib version of net/http requires net/protocol relatively, since that's what it used to happen before these gems were gemified. See [ruby/net-http@6da598e](https://github.com/ruby/net-http/commit/6da598e928f0cc817b1d17209dfaf7fed4c9dff7). So the stdlib version of net/protocol is loaded.
  • Then when net-imap is required, it also uses net-protocol but this time the gemified version of net-protocol is used, because net-imap properly declares it as a dependency, so bundler knows about it and has put it in the $LOAD_PATH. This is what causes the double load of net/protocol.

つまり

faraday-net_httpが要求されると、net/httpが必要になる。

しかし、net-httpがgemの依存関係であることをBundlerが認識していないため、gem化されたバージョンが$LOAD_PATHに追加されず、標準ライブラリのnet/httpがロードされる。

そして、標準ライブラリnet/httpnet/protocolを必要とするのでnet/protocolがロードされる。

そして、net-imapもまた、net-protocolを必要とする。

なのでnet-protocolが二重で呼ばれるのでエラーとなる。

となると、そもそも標準ライブラリのnet/httpを使わせなければいい。つまり、gem版のnet-httpをインストールすればいい。という感じ。

GitHubで編集を提案

Discussion