· トラブル対処 · 約8分

V2Rayコアの起動トラブル対処

ログレベルごとに、JSON構文エラーやポート競合、未知のプロトコルフィールド、ルーティング設定の誤りを解説し、修正方法を紹介します。

この記事の概要

v2rayNでコアの起動に失敗する、v2rayNGが起動直後に終了する、独自設定を変更した後に読み込めなくなった場合に役立ちます。まず設定の読み込み失敗と、起動後の接続失敗を切り分けましょう。ログに記録された原因からJSON、待ち受けポート、プロトコル、ルーティングの各設定を確認し、一度に一つずつ修正します。最後に設定テストと実際のリクエストで、それぞれ動作を確認してください。

まず失敗した段階を見極める

「ウェブページが開かない」からといって「コアが起動していない」とは限りません。クライアントの画面が開いていても、バックグラウンドのコアが正常に動作しているとは限りません。起動時には設定を読み込み、インバウンドとアウトバウンドを構築してから、ローカルの待ち受けを開始します。これらが完了して初めて、アプリのリクエストがルーティング判定に進みます。

設定の読み込み フィールドの構築 ポートの待ち受け リクエストのルーティング リモート接続

v2rayNはデスクトップクライアントで、使用できるフィールドは選択中のコアによって異なります。v2rayNGはXray、v2flyNGはV2Flyを使用します。設定に共通点はありますが、すべての拡張フィールドを相互に使えるわけではありません。トラブルの記録には「最新版」とだけ書かず、クライアントとコアのバージョンをそれぞれ記載してください。

起動ログを最初から最後まで保存する

接続ボタンを何度も押すのはやめ、現在の設定をバックアップしてから、ログ表示欄を消去するか時刻を記録します。起動は一度だけ行い、コアのバージョン表示から終了情報までのログを保存してください。v2rayNGではサイドバーの「ログ」を開きます。v2rayNではメイン画面の情報出力欄を確認します。画面構成や入口はバージョンによって異なるため、コアの起動情報を目印にしてください。

loglevel主な用途確認するポイント
errorエラーを記録読み込みや接続の失敗原因を確認する
warning警告とエラーを確認警告が今回の終了に直接関係しているか
info動作状況を補足起動処理とリクエスト処理の状況
debug一時的に詳しく調査内部処理の詳細な手がかり
none該当するログを無効化トラブル対処中は使用しない

独自のJSON設定では、一時的にlog.loglevelをdebugに設定すると、ログの情報量を増やせます。ただし、エラーが修正されるわけではありません。JSON自体を解析できない場合、この設定が反映されていない可能性もあります。その場合はプロセスの出力、またはクライアントが取得した標準エラーを確認してください。

{
  "log": {
    "loglevel": "debug"
  }
}

タイムスタンプと接続IDを手がかりに、同じ操作のログを関連付けます。>が複数含まれるエラーは、原因が段階的に付け加えられたエラーチェーンであることがよくあります。今回の起動に関係する最初の失敗を見つけ、チェーンの末尾にある具体的な原因まで確認してください。最も外側のFailed to startだけを切り取ったり、それ以前の別リクエストのタイムアウトを混ぜたりしないようにしましょう。

JSON構文エラー:まず構造を直し、次にフィールドを確認

JSONの解析に失敗している間は、通常、プロトコルやDNS、ルーティングの構築まで進んでいません。よくある原因は、末尾の余分なカンマ、閉じ忘れた二重引用符、コピー時に混入した全角の引用符、数値フィールドを文字列として記述したことなどです。エラー位置は問題の箇所より後になる場合もあります。解析器が次の文字を読んだ時点で、直前の構造が不完全だと判明するためです。

エラー:invalid character '}' looking for beginning of object key string

原因:オブジェクトの終了前にフィールド名が必要な状態です。最後のフィールドの後に余分なカンマがある場合によく発生します。

対処法:閉じ波括弧の直前の行を確認し、末尾の余分なカンマを削除します。また、オブジェクト内のキー名が半角の二重引用符で囲まれていることを確認してください。

エラー:unexpected EOF

原因:入力が途中で終わっています。閉じ括弧や引用符が不足しているか、保存時にファイルが途中で切れた可能性があります。

対処法:最後に編集した箇所から、括弧や引用符の対応関係を確認します。ファイルが明らかに不完全な場合は、まずバックアップを復元し、その後、変更を少しずつやり直してください。

エラー:cannot unmarshal string into Go struct field

原因:フィールドのデータ型がコアの想定と異なります。続くログに、フィールドのパスと想定される型が示されることがあります。

対処法:フィールドの完全なパスをたどって型を確認します。たとえば、ローカルのインバウンドポートは"port": 10808のように数値で指定し、引用符付きの数値文字列にしないでください。

ここに挙げたのは、よくあるエラーの一部です。エラーの前置きや大文字・小文字、フィールドのパスはコアのバージョンによって異なります。機械的な一括置換は避けてください。ポートは数値で指定しますが、数字を含む項目をすべて引用符なしにするわけではありません。UUID、アドレス、タグは文字列です。

  1. JSONの検査に対応したローカルエディターで、実際に読み込まれるファイルを開きます。
  2. エディターが示す最初の構文エラーを修正し、再チェックしてから次のエラーに進みます。
  3. 標準のJSONでは、末尾のカンマやコメントは使えません。一部のローダーが拡張構文を受け付ける場合でも、トラブル対処時は標準のJSONを使ってください。
  4. クライアントのフォームから設定を生成している場合は、該当する設定項目を変更してください。一時生成されたファイルを直接編集すると、次回の起動時に上書きされることがあります。

ポート競合:権限をむやみに上げず、使用中のプロセスを特定する

インバウンドの作成に失敗する原因として、2つのクライアントが同じアドレスとポートで待ち受けているケースや、前回起動したプロセスが終了せずに残っているケースがよくあります。以下のポート番号は説明用であり、すべてのクライアントの標準値を示すものではありません。まずログまたは現在の設定で実際のポートを確認し、コマンド内の数字を置き換えてください。

10808
SOCKSインバウンドのポート例
10809
独立したHTTPインバウンドのポート例
1
切り分け時に残すクライアントのインスタンス

エラー:address already in use

原因:指定した待ち受けアドレスとポートが使用中か、既存の待ち受け範囲と競合しています。

対処法:待ち受け中のプロセスを特定し、重複しているインスタンスを正常終了します。複数のインスタンスを同時に動かす必要がある場合は、インバウンドに別のポートを割り当て、アプリのプロキシ設定も合わせて変更してください。

エラー:Only one usage of each socket address

原因:Windowsのソケットバインドが競合しています。通常、完全なエラーにはローカルアドレスとポートも表示されます。

対処法:ログに記載されたポートを使って、待ち受け中のPIDを調べます。管理者として実行することを、ポート競合全般の解決策と考えないでください。

Windows:待ち受け中のPIDを確認する

Get-NetTCPConnection -LocalPort 10808 -State Listen |
  Select-Object LocalAddress, LocalPort, OwningProcess

PowerShellで実行した後、タスクマネージャーの「詳細」タブでPIDとプロセスを照合します。プロセスの所有者を確認してから終了してください。ポートを基準に、正体のわからないシステムプロセスをまとめて終了してはいけません。待ち受け結果が何も表示されない場合は、ログ全体を確認し、競合ではなく権限不足やアドレスが利用できないというエラーが出ていないか調べます。

Linux・macOS:待ち受け中のプロセスを確認する

# Linux
ss -ltnp 'sport = :10808'

# macOS
lsof -nP -iTCP:10808 -sTCP:LISTEN

一般ユーザーでは、ほかのユーザーのプロセス情報をすべて確認できないことがあります。必要な場合も、権限を上げるのは照会コマンドだけにしてください。クライアント全体を長時間、高い権限で実行するのは避けましょう。ローカルポートを10808から10810に変更した場合は、ブラウザーやシステムプロキシ、手動設定したアプリのポートも合わせて更新します。

プロトコルやフィールドのエラー:使用中のコアを確認する

JSONの形式が正しいことは、ファイルを解析できるという意味であり、コアがそのプロトコルを理解するとは限りません。protocolの値は、vmess、vless、socks、freedomのように正確に記述する必要があります。インバウンドとアウトバウンドではsettingsの構造が異なります。サーバー側でユーザーを受け入れるフィールドを、そのままクライアントのアウトバウンドに貼り付けないでください。

「未知のプロトコル」は、必ずしも単独のエラー行として表示されるとは限りません。インバウンドやアウトバウンドの読み込みエラーに含まれることもあります。エラーチェーンをたどり、具体的なprotocolの値を実際の設定と照らし合わせてください。見慣れないフィールドでエラーが出なかったとしても、反映されたとは限りません。未知のJSONフィールドが無視されることもあるため、使用中のコアのドキュメントと実際の動作で確認が必要です。

ルーティングのエラー:条件とアウトバウンドタグを確認する

ルーティングルールは、コアに入った接続を特定のアウトバウンドに振り分けます。routing.rulesは上から順に照合されます。大まかな条件のルールを先に置くと、後続のより具体的なルールが適用されないことがあります。この種の設定は起動できても、「すべて直接接続される」「特定のドメインが誤った経路を通る」といった問題につながります。起動失敗の原因となる構造上の問題とは分けて対処してください。

エラー:this rule has no effective fields

原因:ルールに有効な照合条件がありません。たとえば、typeとoutboundTagだけが残っている場合です。

対処法:domain、ip、port、networkなどの条件を明示的に追加するか、不要な空ルールを削除します。

以下は切り分けテスト用の、簡略化した完全な設定例です。ローカルの127.0.0.1:10808でSOCKSインバウンドを提供し、example.comとそのサブドメインをブロック用アウトバウンドに割り当てます。それ以外の通信は、最初の直接接続アウトバウンドを使用します。リモートのプロキシノードは含まれていないため、正式なノード設定の代わりにはなりません。

{
  "log": {
    "loglevel": "info"
  },
  "inbounds": [
    {
      "tag": "local-socks",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": false
      }
    }
  ],
  "outbounds": [
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {}
    },
    {
      "tag": "blocked",
      "protocol": "blackhole",
      "settings": {}
    }
  ],
  "routing": {
    "rules": [
      {
        "type": "field",
        "domain": ["domain:example.com"],
        "outboundTag": "blocked"
      }
    ]
  }
}
  1. outboundTagとoutbounds[].tagを、大文字・小文字も含めて一字ずつ照合してください。タグが存在しない場合の挙動は、バージョンや処理経路によって異なることがあります。起動できたことだけで正しいと判断しないでください。
  2. ドメインとIPの照合条件には配列を使います。一つのルール内に複数の条件がある場合、通常はすべてを満たす必要があります。「条件を追加する」ことを「いずれかの条件に一致させる」ことと混同しないでください。
  3. エラーにgeosite.datまたはgeoip.datが示されている場合は、使用中のコアのリソースディレクトリ、ファイルの読み取り権限、ルールが参照する分類の有無を確認してください。
  4. リソースの問題を切り分ける間は、上記の明示的なドメインルールで分類リソースを一時的に置き換えられます。動作を確認できたら、元のルールを一つずつ戻してください。

修正後は2段階で動作を確認する

1段階目では、コアが設定を受け付けるかだけを確認します。Xrayのコマンドラインを使う場合は、設定ファイルのあるディレクトリで次のテストコマンドを実行してください。実行ファイルは、クライアントが実際に使用するものと同じバージョンである必要があります。Windowsでは、コマンドの先頭にあるxrayを.\xray.exeに置き換えます。

xray run -test -config ./config.json

設定テストに成功しても、ポートが必ずバインドできるとは限らず、リモートサーバーへの接続が保証されるわけでもありません。2段階目ではクライアントを実際に起動し、新たな待ち受けエラーがないことを確認してから、正しいローカルプロキシポートを通してアプリからリクエストを送信します。サンプル設定ではexample.comを意図的にブロックしているため、このドメインにアクセスできることを確認対象にしないでください。

JSONのチェックに通っても起動に失敗するのはなぜ?

JSONのチェックで確認できるのは構文だけです。コアの出力を引き続き確認し、プロトコルの構築、リソースファイルの読み込み、ポートのバインドのどこで失敗したかを切り分けてください。設定テストを行ってから実際に起動し、それぞれの結果を記録します。

ファイルを直して再接続すると、設定が元に戻るのはなぜ?

クライアントが自動生成した実行用設定を編集した可能性があります。バックアップを取ったうえで、ノード編集、ルーティング設定、カスタム設定などの画面に戻り、元のデータを変更してください。もう一度起動し、生成されたファイルとログに記録された読み込み先を確認します。

コアは起動したのに、タイムアウトがログに出続ける場合は?

アプリのリクエストが実際にローカルのインバウンドに届いているか確認してから、リモートアドレス、ポート、TLSのサーバー名、トランスポートのパスを確認してください。動作中に発生するリモート接続のタイムアウトはJSON構文エラーではありません。設定全体を何度も削除する必要はありません。

クライアントを再インストールすれば、ポート競合は解消する?

再インストールしても、別のプログラムによる待ち受けは自動で解放されません。まず10808など、実際に競合しているポートに対応するPIDを調べ、重複インスタンスを終了するかポートを変更します。その後、アプリのプロキシ設定も合わせて更新してください。

再現可能なトラブル記録には、操作時刻、クライアントとコアのバージョン、読み込んだ設定ファイルのパス、最初のエラーログ、今回変更したフィールド、再テストの結果を含めます。一度に変更する項目を一つに絞れば、ポートを直す過程でルーティングエラーを同時に持ち込む事態を防げます。フィールドの階層を確認するには、設定リファレンスと照らし合わせながら、順に確認してください。

クライアントとインストーラー