「OAuth token revoked」の対処 — Claude Codeの再ログイン手順
Claude Codeで「OAuth token revoked」「OAuth token has expired」が出たときの原因と対処を、/loginの手順からCLAUDE_CODE_OAUTH_TOKEN使用時の挙動まで確認します。
Claude Codeが「OAuth token revoked」または「OAuth token has expired」と表示したら、保存済みのログインをAPIが拒否した状態です。原因は2つに絞れます。サインアウトや管理者によるアクセス削除でトークンが失効している場合と、セッション中の自動更新が途中で失敗した場合です。どちらも対処は/loginの再実行で、同じエラーが同一セッション内で再発するときだけ先に/logoutを挟みます。
Claude Codeが返す3つのメッセージの意味
エラー画面には次のいずれかが出ます。いずれもClaude CodeがAPIへ送ったリクエストに対し、APIが401で拒否した結果を報告するものです。
| メッセージ | 何を意味するか |
|---|---|
OAuth token revoked · Please run /login | 何を意味するか保存済みトークンをAPI側が失効済みと判定した |
OAuth token has expired · Please run /login | 何を意味するかトークンの自動更新(リフレッシュ)がセッション中に失敗した |
API Error: 401 ... authentication_error | 何を意味するか上と同根の401応答を、別の表示経路で報告したもの |
revokedは「どこかで無効化された」、expiredは「更新に失敗した」という原因の違いを示す表現です。全デバイスからサインアウトした、あるいは管理者がアクセスを取り消したときはrevoked、通信の不調やシステム時刻のずれで自動更新が通らなかったときはexpiredになりやすい傾向があります。ただし表示の切り分けは公式でも明確な判定表を出しておらず、どちらが出てもやることは同じです。
管理者による取り消しは、Team・EnterpriseプランでConsole側の管理者がメンバーを削除する操作が典型です。個人利用の場合は、claude.aiのアカウント設定から「すべてのデバイスからサインアウト」を実行した直後に、Claude Codeを開いていた別の端末でこのエラーが出ます。いずれの場合も、対処自体は次に示す/loginの再実行で変わりません。
/loginで再ログインする
対処はシンプルです。ターミナルで/loginを実行し、ブラウザーの認証フローを完了します。
/login再認証後も同じエラーが同じセッション内で返ってくる場合は、古い認証情報が中途半端に残っている可能性があります。/logoutで保存済みトークンを完全に消してから、あらためて/loginを実行します。
/logoutブラウザーが自動で開かない環境(SSH先やコンテナ、WSL2)では、cキーを押して認証URLをクリップボードにコピーし、手元のブラウザーへ貼り付けます。コールバックがローカルに戻らない構成では、代わりにログインコードがそのまま表示されるので、ターミナルに直接貼り付けて完了させます。ログイン方式そのものの選び方はClaude Codeログイン方法3種の使い分けにまとめてあります。
CLAUDE_CODE_OAUTH_TOKENを使っている場合は手順が変わる
CI・ヘッドレス環境でclaude setup-tokenが発行した長期トークンをCLAUDE_CODE_OAUTH_TOKEN環境変数に設定している場合、事情が違います。この変数が設定されているセッションでは、Claude Codeは401が返ってもログイン済みの別の認証情報へ切り替えません。変数の値をそのまま送り続けます。/statusを実行すると「Auth token」の行がCLAUDE_CODE_OAUTH_TOKENと表示され、現在アクティブな認証元がこの環境変数であることを確認できます。
対処は次のいずれかです。
claude setup-tokenで新しいトークンを発行し直し、環境変数を更新してからClaude Codeを再起動する- 環境変数を
unsetし、/loginでブラウザー認証に切り替える
CI・ヘッドレス環境ではブラウザー認証ができないため、前者の再発行が現実的な選択肢になります。手元の端末でclaude setup-tokenを実行し、発行された値をCIの環境変数(GitHub ActionsのSecretsなど)に設定し直します。ローカル開発で手軽に使いたいだけなら、後者の/loginへの切り替えのほうが手順は少なくて済みます。
v2.1.225より前のClaude Codeには、この変数の値をセッション中に保存済みログインの短期アクセストークンへ勝手に置き換えてしまう挙動があり、その短期トークンが切れると再び401が発生していました。v2.1.225以降はこの置き換えが起きなくなり、環境変数の値をそのまま使い続けます。
再発する場合に確認する3点
/loginをやり直しても同じエラーが繰り返される、あるいは頻度が高いと感じる場合は、次を順に確認します。
システムクロックのずれ。トークンの検証は端末の時刻に依存するため、時刻がずれていると正しいトークンでも失効扱いになります。OSの時刻自動同期が有効か確認します。
macOSのKeychainロック。Keychainがロックされている、またはパスワードがアカウントのパスワードと同期していないと、認証情報の保存自体が失敗します。claude doctorでKeychainアクセスを確認できます。手動で解除する場合は次を実行します。
security unlock-keychain ~/Library/Keychains/login.keychain-dbこれで直らない場合は、Keychain Accessアプリでloginキーチェーンを選び、「編集 > キーチェーン"login"のパスワードを変更」からアカウントのパスワードに合わせて再同期します。この手順が該当するのはmacOSだけです。LinuxとWindowsは暗号化ストアではなくファイルに認証情報を保存する方式のため、Keychainのロックという概念自体がありません。
並行セッションの競合。同じマシンで複数のClaude Codeセッションを同時に開いている場合、保存済みログインは共有され、リフレッシュは1プロセスずつ順番に行われます。v2.1.211より前は、スリープからの復帰時に2つのセッションが同じトークンで同時に更新を試み、結果として保存済みログイン自体が失効し、開いていた全セッションが一斉に再ログインを求められることがありました。v2.1.211以降はこの競合が解消されています。
Remote Controlセッション中に出る関連エラー
Remote Controlを使っているセッションでは、同じ根本原因が専用の文言で表示されます。
Claude.ai login expired/Claude.ai login was rejected: claude.aiが保存済みログイントークンを失効または取り消し済みとして拒否したOAuth token unavailable: 資格情報の更新が必要になった時点で、保存済みトークンが存在しなかったOAuth token refresh failed: 保存済みログインの更新を試みたが、OAuthサービスがリフレッシュトークンを拒否したJWT refresh failed: no OAuth token: 更新に使う保存済みトークンが見つからなかった
対処はどの文言でも/loginで再サインインする点は共通です。メッセージが「run /login to restore Remote Control」で終わる場合は/remote-controlの再実行は不要で、サインインすればClaude Codeが自動で再接続します。それ以外の文言では、/loginのあとに/remote-controlを実行してセッションを再開します。Claude.ai login expired・Claude.ai login was rejected・OAuth token unavailableの3つはv2.1.225で追加された文言です。
似た文言の別エラーと混同しない
「認証が切れた」系のエラーはいくつかあり、対処が微妙に違います。表示のタイミングで見分けられます。
| エラー | 発生するタイミング | Claude Codeの挙動 | 対処 |
|---|---|---|---|
| OAuth token revoked / expired | 発生するタイミングAPIが401を返した後 | Claude Codeの挙動エラーをそのまま表示してリクエストは失敗 | 対処/login(再発時は/logoutを先に) |
| Login expired | 発生するタイミングClaude Code内部でリフレッシュ失敗を検知した時点 | Claude Codeの挙動リクエストを送らずローカルで停止 | 対処/login |
| API Error: 401 Invalid authentication credentials | 発生するタイミングAPIが401を返した後(組織やアカウント自体が原因) | Claude Codeの挙動エラー表示、/loginだけでは直らないことがある | 対処/statusで認証元を確認し、ANTHROPIC_API_KEYのローテーションや組織側の復旧を依頼 |
「Login expired」はAPIへリクエストすら送らずローカルで止まる点が違います。すでに認証情報がクリアされているため、/statusを実行すると「Login」の行に「Expired — log in again」と表示されます。一方、この記事が扱う「OAuth token revoked / expired」はAPIが実際に401を返した結果です。両者は見た目が似ていますが原因の切り分け方が異なるため、/loginを実行する前に、どちらのメッセージが出ているかを確認しておくと再発時の判断が早くなります。
よくある質問
/loginしても同じメッセージが出続けるのはなぜですか
古い認証情報がキャッシュに残っている可能性が高いです。/logoutで完全にクリアしてから/loginをやり直します。それでも直らない場合はシステムクロックとmacOSのKeychain状態を確認します。
CIや非対話環境(-p)ではどう対処しますか
ブラウザー認証ができない環境では、claude setup-tokenで発行した長期トークンをCLAUDE_CODE_OAUTH_TOKENに設定するか、ANTHROPIC_API_KEYで認証します。トークンが失効した場合はclaude setup-tokenを再実行して新しい値に差し替えます。
OAuth token revokedとOAuth token has expiredはどちらが深刻ですか
深刻さに差はありません。どちらもAPI側が保存済みトークンを拒否した状態で、対処は同じく/loginです。revokedは無効化、expiredは更新失敗という原因の違いを示す表現にすぎません。
複数セッションを同時に開いていると起きやすいですか
v2.1.211より前はスリープ復帰時の競合で起きやすい状況がありました。v2.1.211以降は保存済みログインのリフレッシュが1プロセスずつ順番に行われるよう調整されており、この種の連鎖的な再ログインは起きにくくなっています。
Remote Controlのセッションだけこのエラーが出ます
Remote Control固有の文言(Claude.ai login expiredなど)が出ている場合は、通常のOAuth token revoked / expiredとは表示形式が異なるだけで原因は同根です。/loginで再サインインし、メッセージが/remote-controlの再実行を案内していれば実行します。「run /login to restore Remote Control」で終わるメッセージは自動で再接続するため、追加の操作は不要です。
ANTHROPIC_API_KEYが設定されていると挙動は変わりますか
ANTHROPIC_API_KEYを承認済みの状態で設定していると、そちらが優先的な認証情報として使われ、/loginの結果は上書きされません。想定と違うアカウントで動いている場合は、Claude Codeアカウント切り替えの優先順位の説明を確認してからunset ANTHROPIC_API_KEYを試すと切り分けやすくなります。ほかのエラーとあわせて典型的な失敗パターンを俯瞰したい場合はClaude Codeでよくあるエラー10選も参考になります。