プログラミングの話題を書くのは久々な気がします。
先ほど、何となく「Windows/Cygwin の方の gem もアップデートしておくかぁ」と思い立ちました。ここで無事にアップデート完了したまでは良かったのですが、それ以降 gem install/update と叩くと、パッケージに関わらず常に「invalid byte sequence in UTF-8」のエラーが返ってくると言う状況に陥りました。
clown@guarneri ~ $ ruby --version ruby 1.9.3p484 (2013-11-22) [i386-cygwin] clown@guarneri ~ $ gem --version 2.2.2 clown@guarneri ~ $ locale LANG=ja_JP.UTF-8 LC_CTYPE="ja_JP.UTF-8" LC_NUMERIC="ja_JP.UTF-8" LC_TIME="ja_JP.UTF-8" LC_COLLATE="ja_JP.UTF-8" LC_MONETARY="ja_JP.UTF-8" LC_MESSAGES="ja_JP.UTF-8" LC_ALL=
上記の環境で実行した際に表示されたバックトレースは以下の通りです(一部、省略)。
clown@guarneri ~ $ gem update nokogiri Updating installed gems ERROR: While executing gem ... (ArgumentError) invalid byte sequence in UTF-8 /usr/lib/ruby/1.9.1/win32/registry.rb:174:in `tr' /usr/lib/ruby/1.9.1/win32/registry.rb:174:in `initialize' /usr/lib/ruby/1.9.1/win32/registry.rb:232:in `exception' /usr/lib/ruby/1.9.1/win32/registry.rb:232:in `raise' /usr/lib/ruby/1.9.1/win32/registry.rb:232:in `check' /usr/lib/ruby/1.9.1/win32/registry.rb:285:in `QueryValue' …(中略)… /usr/lib/ruby/site_ruby/1.9.1/rubygems/command_manager.rb:137:in `run' /usr/lib/ruby/site_ruby/1.9.1/rubygems/gem_runner.rb:54:in `run' /usr/bin/gem:21:in `<main>'
めんどくさくなったので放置しようかとも思いましたが……一応エラーを追ってみると、何らかの別の理由で例外が発生してエラーメッセージを取得する際にコケていました。
# /usr/lib/ruby/1.9.1/win32/registry.rb:168 def initialize(code) @code = code msg = "\0".force_encoding(Encoding::ASCII_8BIT) * 1024 len = FormatMessageA.call(0x1200, 0, code, 0, msg, 1024, 0) msg = msg[0, len].force_encoding(Encoding.find(Encoding.locale_charmap)) super msg.tr("\r", '').chomp end
どうやら、取得したメッセージ (CP932) を強制的に UTF-8 として認識させた上で改行コードを取り除こうとしたため「invalid byte sequence in UTF-8」が発生したと言うもののようです。今回のエラー自体は rubygems.org の名前解決時に発生していたようですが、それ以外の場合でも、レジストリから値を取得するのに失敗した時には同様のエラーが出そうな予感がします。
修正方法ですが、現状は常に "error" と言う文字列を返すと言う思考停止な方法でスルーしています……