Failed to start OAuth callback serverの原因と回避 — Claude Code
Claude Codeのログインが「Is port 0 in use?」で止まる原因と、setup-tokenとCLAUDE_CODE_OAUTH_TOKEN、ANTHROPIC_API_KEYでリスナーなしに認証する回避手順をまとめます。
Failed to start OAuth callback server: Failed to start server. Is port 0 in use? と出てログインが止まるのは、ブラウザーの結果を受け取る 127.0.0.1 のリスナーを、Claude Codeが開けなかったからです。ブラウザーもログインURLも出ないまま終わります。その場で進めたいなら、claude setup-token で作ったトークンを CLAUDE_CODE_OAUTH_TOKEN に入れるか、ANTHROPIC_API_KEY を使います。
このエラーが出る場面と意味
Claude Codeは、/login、claude auth login、claude setup-token のいずれかでブラウザー経由のサインインをするとき、127.0.0.1 で待ち受けるポートを開きます。ブラウザーがサインインの結果をそこへ返す仕組みです。このポートを開けないと、次のメッセージでサインインが止まります。
Failed to start OAuth callback server: Failed to start server. Is port 0 in use?末尾が Is port 0 in use? の場合、IPv4のループバックアドレス 127.0.0.1 での待ち受けが、そもそも成立していません。これは「ポートが使用中」ではなく、リスナー自体を開けない失敗です。表示される番号は0で、調べられる特定のポートがありません。
この時点ではログインURLがまだ作られていません。そのため Paste code here if prompted のプロンプトにコードを貼る手順も使えません。WSL2やSSHで使うコード貼り付けの回避策が効かない点が、他のログイン不具合との大きな違いです。
似たエラーとの見分け方
認証まわりのメッセージは似ています。最初に確認したいのは、ログインURLが出たかどうかです。
| 症状 | 原因の方向 | 使える手段 |
|---|---|---|
Failed to start OAuth callback server(Is port 0 in use?) | 原因の方向127.0.0.1 のリスナーを開けない | 使える手段setup-token、APIキー、リスナーを許す環境への移動 |
| ブラウザー認証後にログインコードだけ表示される | 原因の方向ブラウザーが別ホストで、リダイレクトが届かない | 使える手段コードを Paste code here if prompted に貼る |
OAuth callback port <port> is already in use | 原因の方向MCPのOAuthで固定したポートを他プロセスが占有 | 使える手段lsof などで占有プロセスを特定する |
最後の行はMCPサーバーへのサインインの話で、手順はOAuth callback port is already in useの原因と対処にあります。こちらは番号付きのポートが衝突する場合で、ポート0のエラーとは別の状態です。
リスナーなしで認証する2つの方法
公式の対処は、リスナーを必要としない認証へ切り替えることです。claude.aiのサブスクリプションを使うか、Claude ConsoleのAPIキーを使うかで経路が分かれます。
サブスクリプションならsetup-token
サインインが通る別のマシンで claude setup-token を実行します。ブラウザー認証の流れは /login と同じで、承認すると有効期間1年のOAuthトークンが端末に表示されます。トークンはどこにも保存されません。表示された値をコピーし、困っているマシンの CLAUDE_CODE_OAUTH_TOKEN に設定します。
# サインインできるマシンで実行する
claude setup-tokenmacOS、Linux、WSLでは export で設定します。
# リスナーを開けないマシンで設定する
export CLAUDE_CODE_OAUTH_TOKEN=your-token
claudePowerShellでは $env:CLAUDE_CODE_OAUTH_TOKEN = "your-token"、コマンドプロンプトでは set CLAUDE_CODE_OAUTH_TOKEN=your-token です。
起動後に /status を開くと、使われている認証が確認できます。CLAUDE_CODE_OAUTH_TOKEN から読んでいる場合は、Auth token の行にその変数名が出ます。
このトークンには制約があります。
- Pro、Max、Team、Enterpriseのいずれかのプランが前提
- モデルへのリクエストだけに使える。Remote Controlのセッションも、claude.aiのコネクタ取得もできない
- ローカルで設定したMCPサーバーは引き続き使える
--bareを付けるとCLAUDE_CODE_OAUTH_TOKENは読まれない。その場合はANTHROPIC_API_KEYかapiKeyHelperを使う
Fable 5をsetup-tokenで使うときの使用量クレジットの話は、Fable 5がsetup-token利用時に使用量クレジットを要求される原因と対処法にまとまっています。
サブスクリプションを使わないならAPIキー
claude.aiのサブスクリプションがない場合は、Claude Consoleで発行したキーを ANTHROPIC_API_KEY に設定します。
export ANTHROPIC_API_KEY=your-api-key
claude対話モードでは、初回にこのキーを使うかどうかを一度だけ尋ねられ、答えは記憶されます。-p の非対話モードでは、キーがあれば常にそれが使われます。
キーを固定で置きたくないならapiKeyHelper
APIキーを環境変数に直接置かず、コマンドの出力から取りたい場合は apiKeyHelper を使います。設定した命令をシェル経由で実行し、その出力をモデルへのリクエストの認証情報として送る仕組みです。短い期間で入れ替わるトークンを金庫から取り出す、といった用途に向いています。--bare を付けた実行でも、CLAUDE_CODE_OAUTH_TOKEN の代わりになる経路のひとつです。
{
"apiKeyHelper": "/bin/generate_temp_api_key.sh"
}設定ファイルのどの層にも書けます。出力は5分間キャッシュされ(間隔は CLAUDE_CODE_API_KEY_HELPER_TTL_MS で変えられます)、APIが401か403を返したときにも再実行されます。プロジェクトや個人の設定ファイルに書いた場合、対話セッションではワークスペースの信頼を承認するまで実行されません。
スクリプトがエラー終了する、何も出力しない、キー以外のログ行やバナーを出力する、のいずれかだと、Your apiKeyHelper script is failing が出てリクエストが401で拒否されます。ログインの代わりに仕込むなら、スクリプトを単体で実行して、キーだけが標準出力に出ることを先に確かめておくと切り分けが速くなります。
2つの変数を両方入れたときの優先順位
トークンとAPIキーを同じ環境に置くと、どちらが効くかが問題になります。公式の優先順位では、ANTHROPIC_API_KEY が3番目、CLAUDE_CODE_OAUTH_TOKEN が5番目です。数字の小さいほうが先に使われるので、両方あればAPIキーが勝ちます。/login による保存済みのログインは7番目で、さらに後ろです。
サブスクリプションでもConsoleのAPIキーでもない選択肢もあります。CLAUDE_CODE_USE_BEDROCK、CLAUDE_CODE_USE_VERTEX、CLAUDE_CODE_USE_FOUNDRY のいずれかを設定すると、クラウドプロバイダーの認証情報が1番目に使われます。これらはブラウザーのコールバックを使わないので、組織がクラウド経由のアクセスを用意しているなら、このエラーを避ける第3の経路になります。さらにClaude appsゲートウェイにサインイン済みのセッションは、この一覧の外にあって、クラウドプロバイダーよりも優先されます。
組織が無効になったAPIキーが残っていると、サブスクリプションが生きていても認証に失敗します。切り分けるときは、ANTHROPIC_API_KEY を外して /status を見ます。ログインとAPIキーの両方が設定されている場合、/status は使われていないほうに印を付けます。
CLAUDE_CODE_OAUTH_TOKEN を設定している状態で /login を実行すると、現在のセッションだけが新しいログインに切り替わります。次のセッションでは変数が再び読まれるので、完全に外すにはシェルのプロファイルや設定ファイルの env から消します。
トークンが失効したとき
失効や取り消しのあとは、次のようなメッセージで止まります。対話モードでは OAuth token revoked · Please run /login、あるいは API Error: 401 OAuth token has expired を含む行です。-p の非対話モードでは Failed to authenticate: OAuth token revoked. Please log in again or contact your administrator. のように出て、エラーコードは authentication_failed です。取り消しは、あらゆる場所でサインアウトした場合や、管理者がアクセスを外した場合に起きます。
CLAUDE_CODE_OAUTH_TOKEN で認証している場合、401が返っても、Claude Codeは保存済みログインのトークンに切り替えず、設定した値を送り続けます。/status の Auth token 行に CLAUDE_CODE_OAUTH_TOKEN と出ていれば、原因はこの変数の値です。対処は次のどちらかです。
claude setup-tokenで新しいトークンを作り、変数を差し替えて再起動する- 変数を
unsetして、/loginでサインインし直す
v2.1.225より前は、セッション途中で変数の値が保存済みログインの短命なアクセストークンに置き換わることがあり、そのトークンの期限が切れるとまた401になりました。古いバージョンで、再現のしにくい401が出る場合は、更新で解消している可能性があります。変数に入れた値は、/login を実行しない限りセッション中ずっと使われ続けます。
ブラウザーのログインを使い続けたい場合
マシン上でブラウザー経由のサインインを使いたいなら、Claude Codeが 127.0.0.1 で待ち受けられる環境が前提です。サンドボックスの中で動かしているなら、そのポリシーがローカルポートでの待ち受けを許しているかを確かめます。許可を直してから /login をやり直します。
許可されているはずなのに失敗する場合は、/feedback を実行します。環境の詳細がレポートに入ります。
混同しやすいのが、コマンド実行用の sandbox 設定です。公式のsandboxingページにある network.allowLocalBinding は、サンドボックス内で動くコマンドがネットワークポートで待ち受けるための設定で、macOSでの話として書かれています。LinuxとWSL2では、サンドボックス内のコマンドから見た localhost はそのコマンド専用で、allowLocalBinding は効きません。ログインのリスナーが開けないときの対処としては、この設定は挙がっていません。Claude Code全体を外側から包む構成はsandbox-runtime(srt)の記事が扱っています。
回避策で引っかかりやすい3点
どれも、設定したつもりなのに認証が通らない、という形で現れます。
- トークンを控え損ねる。
claude setup-tokenはトークンをどこにも保存しません。端末に出た値をコピーし損ねたら、もう一度実行して発行し直します。 - 変数を一時的にしか設定しない。
exportは、そのシェルの中でしか効きません。新しいシェルや、別の経路で起動したエディターから使うなら、シェルのプロファイルか、設定ファイルのenvに書く必要があります。逆に外したいときも、同じ場所から消さないと、次のセッションで再び読まれます。 - 古い
ANTHROPIC_API_KEYが残っている。優先順位ではAPIキーがCLAUDE_CODE_OAUTH_TOKENに勝ちます。組織が無効になったキーが環境に残っていると、新しいトークンを作っても認証に失敗します。トークンが通らないときは、先にunset ANTHROPIC_API_KEYを試して/statusを見ます。
判断の流れ
エラーが出たときの順序をまとめます。
- メッセージが
Is port 0 in use?で終わっているか確認する - ブラウザーが使えて別のマシンでサインインできるなら、そこで
claude setup-tokenを実行し、トークンを持ち帰る - サブスクリプションがなければ、
ANTHROPIC_API_KEYを設定する - 設定後に
/statusを見て、狙った認証が使われているかを確かめる - このマシンでブラウザーログインを続けたいなら、サンドボックスのポリシーを確認する
CIやスクリプトのように、そもそも対話ログインができない環境では、最初から手順2か3の形で組んでおくと、このエラーに当たりません。非対話で動かす設定はClaude Codeのヘッドレス実行(-pモード)の記事に詳しくあります。
ログインが繰り返し求められる別の症状はClaude Codeで何度もログインを求められる原因と対処法で扱っています。
まとめ
Is port 0 in use? は、ポートの取り合いではなく、ループバックでのリスナーが開けない失敗です。コード貼り付けは使えないので、リスナーを使わないsetup-tokenかAPIキーに切り替えるのが近道です。ブラウザーログインに戻したいときは、サンドボックスのポリシーが 127.0.0.1 の待ち受けを許しているかを見直します。