MacでCodexを使っていると、Reconnecting... が繰り返し表示され、接続できなくなることがありました。CLIとデスクトップアプリの両方で発生し、再起動しても直りませんでしたが、しばらく待つと復旧しました。

自分の環境で4回発生したため調べたところ、macOSのmDNSResponderに残ったDNSの否定応答キャッシュが原因だと分かりました。

DNSキャッシュを削除すると復旧した

私の環境では、次のコマンドを実行すると復旧しました。

sudo dscacheutil -flushcache && sudo killall -HUP mDNSResponder

この1行では、2つのコマンドでキャッシュを削除しています。

  • dscacheutil -flushcache:macOSのDirectory Serviceが持つキャッシュを消します。-flushcacheが「キャッシュを空にする」という指定です。
  • killall -HUP mDNSResponder:DNSの問い合わせと応答のキャッシュを管理するmDNSResponderに、HUPというシグナル(処理を求める通知)を送ります。mDNSResponderはこの通知を受けると、内部のDNSキャッシュを削除して問い合わせをやり直します。これはAppleの公開実装でも確認できます。

私の環境では、mDNSResponderのキャッシュを削除すると復旧しました。

mDNSResponderのキャッシュが原因なら、sudo killall -HUP mDNSResponderだけでも復旧すると考えられます。ただし、このコマンド単独での復旧は検証できていません。

再接続ループ(Reconnecting)から抜けられない

接続できない間は、次の表示が繰り返されました。

Reconnecting...

その間、次のような状態でした。

  • ブラウザなど他のアプリでは通信できる
  • Codexは再試行しても、アプリを再起動しても接続できない
  • 数十秒〜数十分待つと復旧する

GitHubのopenai/codexリポジトリにも同じパターンのissueが上がっていて、「Wi-Fi切替後に再接続不能→時間経過で自然回復」「DNS解決失敗らしきログが出る」と報告されていますが、原因は未特定のままOPEN状態です。

GitHubCodex app/CLI fail to reconnect after Wi-Fi switch on macOS, possibly DNS/Tailscale related · Issue 30777 · openai/codexAfter switching Wi-Fi networks, Codex app and Codex CLI on macOS can fail to reconnect for a while. The problem recovers automatically after some time.

chatgpt.comだけ名前解決に失敗していた

名前解決を確認すると、chatgpt.comでは失敗し、www.chatgpt.comとapi.openai.comでは成功していました。

ドメイン結果
chatgpt.com解決失敗
www.chatgpt.com正常
api.openai.com正常

Codexの接続先はchatgpt.com/backend-api/...です。このドメインの名前解決に失敗していたため、他のサイトにアクセスできてもCodexには接続できない状態でした。

問い合わせ先によって結果が異なる

接続できない間に次のコマンドを実行すると、約1msでNo Such Recordが返りました。

dns-sd -q chatgpt.com A

このコマンドは、mDNSResponderを経由して名前解決を行います。一方、DNSサーバーに直接問い合わせると、正常な応答が返りました。

dig chatgpt.com @172.20.10.1      # テザリング中のiPhone
dig chatgpt.com @100.100.100.100  # Tailscale MagicDNS
# どちらも正常なAレコード応答

curlやpingでも、1〜3msで名前解決のエラーになりました。DNSサーバーからは正常な応答が返るのに、mDNSResponder経由では失敗します。この結果から、mDNSResponderに残った否定応答のキャッシュを疑いました。

ネットワーク切替後も否定応答が残っていた

症状が出たのは、Wi-FiとiPhoneのテザリングなどを切り替えた後でした。

切替中に一時的な否定応答を受け取り、それがネットワークの復旧後もキャッシュに残っていたと考えています。ただし、切替時にどのDNSサーバーがどの応答を返したかまでは確認できていません。

時間が経つと復旧したのも、キャッシュのTTL(有効期限)が切れたためと考えられます。実際に、何も操作せず待つだけで復旧した回もありました。

sudoが使えない場合

私の環境では、数十秒〜数十分待つことで復旧しました。

待たずに接続する方法としては、DNSサーバーへ直接問い合わせるローカルCONNECTプロキシを用意し、HTTPS_PROXYを設定してCodexを起動する方法もあります。これにより、mDNSResponderを経由せずに名前解決できます。

ネットワーク切替時にキャッシュを自動で削除する

同じ症状が4回発生したため、LaunchDaemonでキャッシュの削除を自動化しました。DNS設定の変更時に更新される/etc/resolv.confを監視します。DNS設定が変わらない切替では実行されない可能性があります。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>local.dnsflush</string>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/sh</string>
        <string>-c</string>
        <string>sleep 2; dscacheutil -flushcache; killall -HUP mDNSResponder; sleep 10; dscacheutil -flushcache; killall -HUP mDNSResponder</string>
    </array>
    <key>WatchPaths</key>
    <array>
        <string>/etc/resolv.conf</string>
    </array>
</dict>
</plist>

切替直後に削除しても、その後の問い合わせで否定応答が再び残る可能性を考え、2秒後と12秒後の2回削除する設定にしています。

上の内容をlocal.dnsflush.plistとして保存し、次のコマンドで登録します。ファイルはroot所有とし、グループや他のユーザーが書き込めない権限にしておきます。

sudo cp local.dnsflush.plist /Library/LaunchDaemons/
sudo chown root:wheel /Library/LaunchDaemons/local.dnsflush.plist
sudo launchctl bootstrap system /Library/LaunchDaemons/local.dnsflush.plist

導入してから約1週間の時点では、同じ症状は再発していません。

まとめ

今回の再接続ループは、ネットワーク切替後に残ったDNSキャッシュが原因でした。sudo killall -HUP mDNSResponderでmDNSResponderのキャッシュを削除すると復旧しました。

Blogへ戻る