本文へ移動

サーバー版で困ったとき ​

部屋のサーバー(Cloudflare版とVercel版)で、よくあるつまずきと、その直しかたをまとめました。上から順に、症状に合うところを探してください。部屋のサーバーのエラーは{"error":"<コード>"}の形で返るので、コードが分かれば、いちばん下の表でも引けます。

まず確かめること ​

ブラウザで、部屋のサーバーのURLの後ろに/v1/login/discordを付けたものを開きます(例:https://backend.example.com/v1/login/discord)。

出たもの意味と、見るところ
{"error":"invalid-request"}部屋のサーバーは正しく動いています。ログインできないか、部屋に入れない・切れるへ
{"error":"login-unavailable"}ログインの3つが入っていません(→ 設定項目)
{"error":"config-invalid"}設定が足りないか、形が違います。下の設定が読めないへ
エラーの画面、何も出ないデプロイが済んでいないか、URLが違います。下のデプロイでつまずくへ

デプロイでつまずく ​

Cloudflare版 ​

Workerの画面のDeploymentsからView build historyを開き、失敗したビルドのログを見ます。

見えるもの原因と直しかた
Please enable R2 through the Cloudflare DashboardアカウントでR2を使い始めていない(→ Cloudflareに置く)
You need to enable Analytics EngineアカウントでAnalytics Engineを使い始めていない(→ Cloudflareに置く)
バケットを作れない、同じ名前のバケットがある前に同じ名前のWorkerを消したあとや、初めてのデプロイが途中で止まったあとで、「<Workerの名前>-assets」が残っている。いらなければ消すか、Workerの名前を変える(→ Cloudflareに置く)
DeployボタンのCreate and deployを押しても進まないGitHubに入れたCloudflare Workers and Pagesのアプリに、リポジトリを作る権限が無い。GitHubのSettingsのApplicationsでアプリを入れ直す
リポジトリを作れない複製先のGitHubのアカウントに、同じ名前のリポジトリがすでにある。リポジトリの名前を変える
Authentication errorCIからデプロイしていて、APIトークンの権限が足りない(→ 自分のリポジトリから自動でデプロイする)

初めてデプロイした直後に、WorkerのURLを開くとエラーの画面が出ることがあります。1分ほど待ってから、開き直してください。

Vercel版 ​

見えるもの原因と直しかた
ビルドが失敗するビルドのログの最後の数行を見る。環境変数の誤りは、ビルドでは見つからない(デプロイしたあとでconfig-invalidになる)
部屋に入れず、WebSocketがすぐ閉じるプロジェクトでFluid computeが切れている(2025年4月より前に作ったプロジェクト)。SettingsのFunctionsで有効にするか、vercel.jsonのfluidを確かめる

設定が読めない ​

config-invalidが返るときは、足りない設定の名前がログに出ています。

  • Cloudflare版:Workerの画面のLogs(またはObservability)を開きます。
  • Vercel版:プロジェクトのLogsを開きます。無料のプランでは1時間しか残らないので、URLを開いた直後に見てください。

よくある原因は、次のとおりです。

  • ログインの3つのうち、一部だけが入っている。SESSION_SECRETが32文字より短い。
  • ACCESS_CONTROL_ALLOW_ORIGINが無い。ROOM_RETENTION_HOURSが1以上の整数でない(Cloudflare版でwrangler.jsoncから消したときも)。ACCESS_CONTROL_ALLOW_ORIGINの形が違う(https://が抜けているなど)ときは、ここではなく、Axeからの要求が403 origin-not-allowedで断られます。
  • Vercel版で、RedisかBlobのストアがつながっていない(REDIS_URLかKV_URL、BLOB_STORE_IDが無い)。

直したあとは、Cloudflare版はシークレットの画面でDeployを、Vercel版はRedeployを押します(→ 設定項目)。

ログインできない ​

見えるもの原因と直しかた
Discordの画面にInvalid OAuth2 redirect_uriと出るDiscordのアプリのRedirectsに、https://<部屋のサーバーのドメイン>/v1/login/discord/callbackが入っていない。ドメインは、Axeのbackend.urlと同じにする(→ Discordのアプリを作る)
Axeに戻ってきたがlogin_error=provider-failed理由は部屋のサーバーのログのDiscord turned the login down at …の行に出る(→ 見ておくところ)。invalid_clientなら、Client IDかClient SecretがDiscordのアプリと合っていない(作り直したときはサーバーの値も替える)。invalid_grantなら、同じコードを2回使った。Axeからやり直す
ログインを始めると400 invalid-requestAxeを開いているページのOriginが、ACCESS_CONTROL_ALLOW_ORIGINに名前で書かれていない(*は数えない)
Axeに戻ってきたがlogin_error=banned運営する人が、送信元のIPアドレスかDiscordのアカウントをBANした。自分で置いた部屋のサーバーなら、管理画面で確かめて解く(→ 管理画面とBAN)
Axeに戻ってきたがlogin_error=paused運営する人が、新しくログインすることを止めている(緊急停止)。自分で置いた部屋のサーバーなら、管理画面の「安全」で再開する(→ 緊急停止)
ログインの途中の画面で止まるログインを始めてから10分のうちにDiscordから戻らなかった(Discordのアカウントを作っていた、など)。Axeからログインをやり直す

*.workers.devで登録したままカスタムドメインから使うときや、Vercel版でプレビューのURL(*-git-*.vercel.appなど)から使うときも、Invalid OAuth2 redirect_uriになります。

部屋に入れない・切れる ​

部屋のサーバーは、接続を閉じる前に理由を送ります。Axeの画面や、開発者ツールのコンソールに出た理由を、次の表で探します。

理由意味と直しかた
つないですぐ403Axeを開いているページのOriginが、ACCESS_CONTROL_ALLOW_ORIGINにない。前は通っていたのに急に出るようになったら、Cloudflare版ではwrangler.jsoncの値に戻っている(→ Cloudflareに置く)
つないですぐ403 banned運営する人が、送信元のIPアドレスをBANした(→ 管理画面とBAN)
protocol-mismatchAxeと部屋のサーバーの版が合わない。Axeを読み込み直す。それでも直らなければ、部屋のサーバーが古いので、新しい版をデプロイする
wrong-passwordパスワードが違う。部屋を作った人に確かめる
room-full部屋に32人いる。誰かが抜けるのを待つ
replaced同じ人が別のタブや端末から入り直したので、古い方を閉じた
room-deleted部屋のGMか、部屋のサーバーを運営する人が部屋を削除した。入るなら作り直す
idleAxeを開いたまま3時間操作しなかったので、部屋から外した。Axeの「部屋に戻る」で入り直す
unauthorizedアクセストークンが切れたか、無効。Axeがトークンを替えてつなぎ直す。繰り返すなら、ログインし直す
banned運営する人が、送信元のIPアドレスかDiscordのアカウントをBANした。Axeはつなぎ直さない(→ 管理画面とBAN)
bad-message送ったものが読めなかったか、ほかの人のピアIDを名乗った
too-many-messages短いあいだに送りすぎた。ふつうに遊んでいて起きるなら、Issuesで知らせてください

見学で入っていた人は、同じユーザーIDやピアIDでログインした本人が入ってきたときにも、unauthorizedやbad-messageで外れます。ログインしてから入り直してください。

Vercel版では、数分ごとに部屋のサーバーが接続を閉じて、Axeが静かにつなぎ直します。ほかの人には何も見えないのがふつうです。数分ごとに「再接続中」が出るときは、ROOM_SOCKET_SECONDSをmaxDurationより長くしていないかを確かめます(→ 設定項目)。

画像が部屋のアセットに上がらない ​

画像を足した人のブラウザで、開発者ツールのネットワークを開き(→ 設置の準備)、/v1/rooms/<部屋の鍵>/assets/へのリクエストを見ます。

  1. リクエストが飛んでいない:部屋に入っていません。Axeは、部屋の外(ロビーで待っているあいだ)では何も上げません。
  2. HEADのあとにPUTが無い:HEADが200なら、その部屋にすでに置かれています。正常です。
  3. PUTが403 not-a-player:見学の席からは置けません。置けるのはGMとPLだけです。Vercel版では、受け持ちのインスタンスが替わった直後に、GMやPLにも返ることがあります。Axeは入り直したあとに上げ直すので、続かなければ心配はいりません。
  4. 403 origin-not-allowed:ACCESS_CONTROL_ALLOW_ORIGINが、Axeを開いているページのOriginと一致していません。
  5. 401 asset-token-required:部屋のアセットのトークンが切れたか、ほかの部屋のものです。部屋に入り直してください。
  6. PUTが415や413:受け付けない形式か大きさです。その画像は、部屋のサーバーの中継で配られます。413 room-storage-fullは、部屋の画像と音声の合計がROOM_STORAGE_LIMIT_MBに達しています。部屋の中の使わない画像や音声を消すか、上限を上げます。
  7. PUTが404 room-not-found:部屋が削除されたか、保持期間を過ぎて消えています。
  8. Vercel版で、大きい音声が置かれない:4,000,000バイトを超えるものは、Blobへ直接上げます。BlobへのPUTが断られていないかを見ます。断られていれば、部屋のサーバーの中継で配られます。

画像が部屋のアセットから届かない ​

ほかの参加者のブラウザで、開発者ツールのネットワークを見ます。

  • GETが404:その部屋にまだ置かれていません。部屋のサーバーの中継で届くので、遊ぶのに困ることはありません。
  • GETが429:送信元からの読み出しが上限を超えています。同じ回線から大勢が参加している(学校や会社のネットワーク、モバイル回線の共有など)と起きやすくなります。Cloudflare版では、READ_LIMITERの上限を上げられます(→ 設定項目)。
  • 混在コンテンツ(Mixed Content)のエラー:Axeがhttps://なのに、backend.urlがhttp://になっています。

部屋が消えない ​

時間を過ぎた部屋は、消える前から一覧に出ず、入ることもできません。中身を消す時刻は、置き場所によって違います。

  • Cloudflare版:部屋ごとのアラームで、時間になると消します。
  • Vercel版:部屋の一覧を取る・部屋を作る・部屋に入るのついでと、1日1回のVercel Cronで消します。そのため、消えるのが1日ほど遅れることがあります。

費用が気になる・遅い ​

  • Cloudflare版を*.workers.devのまま使っている:画像と音声のキャッシュが効かないので、毎回R2から読みます。カスタムドメインを付けてください(→ Cloudflareに置く)。
  • リクエストが多すぎる:どこから多く来ているかを、ダッシュボードで見ます(→ 運用)。Cloudflare版で読み出しを繰り返されているなら、カスタムドメインのゾーンにWAFのレート制限ルールを足します(→ 安全のしくみ)。

エラーのコード ​

コード起きるときすること
config-invalid設定が足りないか、形が違う設定が読めない
login-unavailableログインの3つが入っていない設定項目
origin-not-allowedOriginがACCESS_CONTROL_ALLOW_ORIGINにないAxeを開いているページのOriginを書く
invalid-request本文の形が違う。部屋の名前が空か長すぎる。ログインの戻り先が許されていない名前は1〜255文字、パスワードは64文字まで
login-required部屋を作る・削除する、アカウントを見る・消すのに、ログインしていない(トークンが切れた)ログインし直す
invalid-grantログインのコードやリフレッシュトークンが、無効・使用済み・期限切れログインし直す
asset-token-required部屋のアセットのトークンが無い・切れた・ほかの部屋のもの部屋に入り直す
not-a-player見学の席から画像や音声を置こうとした。Vercel版では、受け持ちが替わった直後のGMやPLにも返る正常な動き。置けるのはGMとPLだけ。GMやPLならAxeが上げ直す
not-game-master部屋を削除しようとしたが、その部屋のGMでない正常な動き。削除はその部屋のGMに頼む
not-foundその部屋に置かれていない(部屋と一緒に消えたときも)。アカウントがもう無い正常な動き。画像は部屋のサーバーの中継で届く
room-not-foundその部屋が無い。作られていないか、消えた部屋を作り直す
unsupported-type受け付けない形式(動画など)正常な動き。その画像は部屋のサーバーの中継で配られる
too-large画像が2MiB、音声が10MiBを超えた正常な動き。その画像は部屋のサーバーの中継で配られる
hash-mismatch本文のハッシュが名前と合わない正常な動き。その画像は部屋のサーバーの中継だけで配られる
rate-limited送信元からの上限を超えた少し待てば戻る。Axeは間を置いて試し直す
blocked運営する人が、その画像を置かせないようにした正常な動き。その画像は使わない
banned運営する人が、送信元のIPアドレスかDiscordのアカウントをBANした管理画面とBAN
paused運営する人が、部屋を作ることか画像と音声を置くことを止めている(緊急停止)運営する人が再開するまで待つ。自分で置いた部屋のサーバーなら、管理画面の「安全」で再開する(→ 緊急停止)
reauth-required管理画面で戻せない操作をする前に、パスキーで確かめてから5分を過ぎた管理画面が求めるとおりに、パスキーでもう一度確かめる
upgrade-required部屋に入るURLを、WebSocketでなく普通のリクエストで開いた正常な動き。部屋にはAxeからつなぐ
internal-error部屋のサーバーの中で失敗した。Vercel版では、Redisが答えないとき(コマンドを使い切ったなど)Vercel版なら、Upstashのダッシュボードでコマンドの数を見る(→ 費用と上限)

部屋のWebSocketがclose code 1011・reason unavailableで閉じるときも、部屋を開けなかった(Vercel版ではRedisが答えない)ことを表します。internal-errorと同じように確かめます。

ほかのコードも含めた一覧は、部屋のサーバーのAPIにあります。

それでも解決しないとき ​

Issuesで知らせてください。エラーのコード、開発者ツールに出たエラー、ログに出たエラーを書いてもらえると助かります。設定の値(特にClient SecretとSESSION_SECRET)は貼らないでください。

MITライセンスで公開しています