📜 要約
### 主題と目的
Supabaseの認証ライブラリGoTrueClientを用いたアプリケーションで表示される
「Multiple GoTrueClient instances detected in the same browser context.」という警告が何を意味し、どのような影響を及ぼし、どのように対策すべきかを明確に解説する。これにより、同一ブラウザコンテキスト内で複数インスタンスが生成されることによる未定義動作やセッション不整合を防ぎ、安定した認証環境を実現することを目的とする。
### 回答
#### 1. 警告の概要
- **内容**
「同じブラウザコンテキスト内でGoTrueClient(Supabaseクライアント)が複数インスタンス生成されました」という情報メッセージで、動作を停止させるエラーではない。
- **意味**
同一のストレージキー(CookieやlocalStorage)を複数クライアントが並行利用すると、トークン更新やセッション取得時に競合し、未定義の動作を招く可能性がある[1](https://www.reddit.com/r/Nuxt/comments/15f5wzo/error_multiple_gotrueclient_instances_detected_in/), [2](https://velog.io/@manner9945/supabase-ERROR-Multiple-GoTrueClient-instances-detected-in-the-same-browser-context-%E3%82%A8%E3%83%A9%E3%83%BC)。
#### 2. 発生しやすい状況
- **フレームワークでのフック重複**
Nuxt.jsの`useSupabaseClient()`やReact/Next.jsのカスタムフックを異なるコンポーネントで呼び出すと、意図せず複数生成されやすい[1](https://www.reddit.com/r/Nuxt/comments/15f5wzo/error_multiple_gotrueclient_instances_detected_in/)。
- **Vercelプレビュー環境**
v0プレビューでログイン直後のセッションが即削除され、ログインページにリダイレクトされる事例。プレビューと本番で挙動差があり、同一コードでも発生[5](https://community.vercel.com/t/session-handling-in-v0-previews/6527)。
- **SSR/CSRの境界**
Next.js App Routerでサーバーコンポーネントとクライアントコンポーネントを混在利用する際、初期化関数を正しく使い分けないと重複する。
#### 3. 潜在的な影響
- **未定義動作(Undefined Behavior)**
セッション取得・更新が競合し、一方のクライアントが更新したトークンを他方が認識せず、リクエスト失敗やセッション破棄に繋がる。
- **認証の不安定化**
JWTアクセストークン/リフレッシュトークンの整合性が崩れ、ログイン状態が途切れたり、無限リダイレクトが発生したりする。
- **デバッグ困難化**
本番とプレビュー環境で再現性が異なるため、原因追究に時間を要する。
#### 4. 対策とベストプラクティス
1. **クライアント生成の一元化(シングルトン)**
全アプリでGoTrueClientインスタンスを一度だけ生成し、共有する。
2. **公式ライブラリ`@supabase/ssr`の採用**
Next.js向けにクライアントを以下の2関数に集約し、SSR/CSRごとに明確に使い分ける[18](https://zenn.dev/kutakutat/scraps/17884d66a25c02)。
| 旧ライブラリ (`@supabase/auth-helpers-nextjs`) | `@supabase/ssr` | 用途 |
|---|---|---|
| createClientComponentClient | createBrowserClient | クライアントコンポーネント |
| createServerComponentClient<br>createServerActionClient<br>createRouteHandlerClient<br>createMiddlewareClient | createServerClient | サーバーコンポーネント・API・ミドルウェア |
3. **ミドルウェアでのセッションリフレッシュ**
Next.js Middlewareを利用し、サーバーコンポーネント読み込み前に`supabase.auth.getSession()`を実行して常に最新化する。
4. **Cookieセキュリティ設定**
- 本番環境では`secure: true`を指定しHTTPS限定送信
- `sameSite: 'lax'`, `httpOnly: false`はSupabase公式推奨のまま利用可能
5. **PKCEフローの理解と活用**
OAuth2.0拡張仕様のPKCEを利用して`signInWithOAuth`などを実装し、安全性を確保する。
#### 5. 実装サンプル
```javascript
// utils/supabaseClient.js
import { createBrowserClient, createServerClient } from '@supabase/ssr'
import { cookies } from 'next/headers'
// CSR用
export const getBrowserClient = () =>
createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
)
// SSR用
export const getServerClient = (cookieStore) =>
createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
{
cookies: {
get: (name) => cookieStore.get(name)?.value,
set: (name, value, opts) => cookieStore.set({ name, value, ...opts }),
remove: (name, opts) => cookieStore.set({ name, value: '', ...opts })
}
}
)
```
### 結果と結論
「Multiple GoTrueClient instances detected…」はエラーではなく警告だが、同一ストレージキーで複数クライアントを動作させると未定義動作やセッション不整合を招く。特にNext.jsやNuxt.js、Vercelプレビュー環境で顕在化しやすいため、以下を徹底することで安定した認証を実現できる。
- `@supabase/ssr`導入によるクライアント生成の明確化
- シングルトンパターンでのインスタンス管理
- Middlewareによるセッションの最新化
- 本番環境でのCookieセキュリティ設定
これらを実践すれば、警告を解消しつつ堅牢なSupabase Auth環境を構築できる。
🔍 詳細
🏷 Multiple GoTrueClient警告とは何か
### Multiple GoTrueClient警告とは何か
「Multiple GoTrueClient instances detected in the same browser context.」というメッセージは、Supabaseを利用したアプリケーション開発において頻繁に遭遇する可能性のある警告です。このメッセージはエラーとしてアプリケーションの動作を停止させるものではありませんが、同一のブラウザコンテキスト内で複数のGoTrueClient(Supabaseクライアントインスタンス)が検出されたことを示しています[1](https://www.reddit.com/r/Nuxt/comments/15f5wzo/error_multiple_gotrueclient_instances_detected_in/), [9](https://velog.io/@manner9945/supabase-ERROR-Multiple-GoTrueClient-instances-detected-in-the-same-browser-context-%E3%82%A8%E3%83%A9%E3%83%BC)。この状態が続くと同じストレージキーの下でクライアントが同時に使用されると、予期せぬ未定義の動作を引き起こす可能性があるため、解決が推奨されています[3](https://www.reddit.com/r/Nuxt/comments/15f5wzo/error_multiple_gotrueclient_instances_detected_in/), [5](https://community.vercel.com/t/session-handling-in-v0-previews/6527), [7](https://github.com/supabase/supabase-js/issues/1394), [2](https://stackoverflow.com/questions/76773817/multiple-gotrueclient-instances-detected-in-the-same-browser-context)。
この警告は、特にNuxt.jsのようなモダンなJavaScriptフレームワークでSupabaseを利用している場合に多く報告されており[3](https://www.reddit.com/r/Nuxt/comments/15f5wzo/error_multiple_gotrueclient_instances_detected_in/), [4](https://github.com/nuxt-modules/supabase/issues/209), [6](https://www.reddit.com/r/Nuxt/comments/15f5wzo/error_multiple_gotrueclient_instances_detected_in/?tl=fil), [8](https://www.answeroverflow.com/m/1234144205790511184)、ユーザーが`useSupabaseUser`と`useSupabaseClient`のようなフックを同時に使用した際に発生した事例も報告されています[6](https://www.reddit.com/r/Nuxt/comments/15f5wzo/error_multiple_gotrueclient-instances-detected-in/?tl=fil)。これは、コンポーネントやレイアウトの異なる箇所で独立してSupabaseクライアントが初期化されている可能性を示唆しており、アプリケーションの規模が大きくなるにつれて発生しやすくなる傾向にあります。
#### 検出される状況と具体的な影響
この警告メッセージは、「"Multiple GoTrueClient instances detected in the same browser context. It is not an error, but this should be avoided as it may produce undefined behavior when used concurrently under the same storage key."」という具体的な形で表示されます[1](https://www.reddit.com/r/Nuxt/comments/15f5wzo/error_multiple_gotrueclient_instances_detected_in/)。あるユーザーの報告では、Nuxt3とSupabaseの古いバージョンでは問題なく動作していたコードが、バージョンアップ後にこの警告が表示されるようになったとされており、`@nuxtjs/supabase`のバージョンアップに伴い、Supabaseクライアントのインスタンス管理に関する挙動に変更があった可能性が考えられます[1](https://www.reddit.com/r/Nuxt/comments/15f5wzo/error_multiple_gotrueclient_instances_detected_in/)。このユーザーが使用していたコードでは、`<script setup>`内で`useSupabaseClient()`フックを直接使用していました[1](https://www.reddit.com/r/Nuxt/comments/15f5wzo/error_multiple_gotrueclient_instances_detected_in/)。
具体的な影響としては、Vercelのv0プレビュー環境で、Supabaseを利用したマルチテナントSaaSプラットフォーム開発において、ログイン後にセッションが作成された直後に削除され、ログインページにリダイレクトされてしまう問題が報告されています[5](https://community.vercel.com/t/session-handling-in-v0-previews/6527), [20](https://community.vercel.com/t/session-handling-in-v0-previews/6527)。この問題は、同じコードでも本番環境では発生しないことから、プレビュー環境と本番環境でのセッション管理の挙動に違いがある可能性を示唆しています[5](https://community.vercel.com/t/session-handling-in-v0-previews/6527)。これは、複数のGoTrueClientインスタンスがセッション管理の整合性を損ない、予期せぬセッションの破棄につながっている可能性が考えられます。
#### Supabaseクライアントの統合と推奨されるライブラリ
Supabaseは、特にNext.jsのようなサーバーサイドレンダリング(SSR)やサーバーコンポーネントを扱うフレームワークでの利用において、クライアントのインスタンス管理を最適化するために`@supabase/ssr`というライブラリを推奨しています[18](https://zenn.dev/kutakutat/scraps/17884d66a25c02)。このライブラリは現在ベータ版ですが、SupabaseクライアントをCookieを使用するように自動的に構成し、ユーザーセッションがNext.jsのスタック全体(クライアント、サーバー、App Router、Pages Router)でシームレスに利用可能になるよう簡素化します[18](https://zenn.dev/kutakutat/scraps/17884d66a25c02), [4](https://zenn.dev/kutakutat/scraps/17884d66a25c02), [11](https://zenn.dev/kutakutat/scraps/17884d66a25c02)。
以前の`@supabase/auth-helpers-nextjs`では、クライアントの用途に応じて5つの異なるクライアント(`createClientComponentClient`, `createServerComponentClient`, `createServerActionClient`, `createRouteHandlerClient`, `createMiddlewareClient`)が提供されていました[18](https://zenn.dev/kutakutat/scraps/17884d66a25c02), [4](https://zenn.dev/kutakutat/scraps/17884d66a25c02)。しかし、`@supabase/ssr`では、以下の2つのクライアントに集約され、より見通しが良くなっています[18](https://zenn.dev/kutakutat/scraps/17884d66a25c02), [4](https://zenn.dev/kutakutat/scraps/17884d66a25c02), [6](https://zenn.dev/kutakutat/scraps/17884d66a25c02)。
| 以前のクライアント (`@supabase/auth-helpers-nextjs`) | 現在のクライアント (`@supabase/ssr`) | 用途 |
|---|---|---|
| `createClientComponentClient` | `createBrowserClient` | クライアントコンポーネント用 |
| `createServerComponentClient` | `createServerClient` | サーバーコンポーネント、サーバーアクション、ルートハンドラー、ミドルウェア用 |
| `createServerActionClient` | `createServerClient` | サーバーコンポーネント、サーバーアクション、ルートハンドラー、ミドルウェア用 |
| `createRouteHandlerClient` | `createServerClient` | サーバーコンポーネント、サーバーアクション、ルートハンドラー、ミドルウェア用 |
| `createMiddlewareClient` | `createServerClient` | サーバーコンポーネント、サーバーアクション、ルートハンドラー、ミドルウェア用 |
この集約は、開発者がSupabaseクライアントを扱う際の複雑さを軽減し、複数のインスタンスが意図せず生成されるリスクを低減することを目的としていると考えられます。特に、Next.jsのようなハイブリッドレンダリング環境では、クライアントサイドとサーバーサイドの両方でセッション管理を適切に行う必要があり、`@supabase/ssr`はこれを効率的に実現するための重要なツールとなります。
#### セッション管理とセキュリティの観点からの考察
Supabase Authで認証が行われると、主にJWT形式のアクセストークンとリフレッシュトークンが発行されます[18](https://zenn.dev/kutakutat/scraps/17884d66a25c02), [6](https://zenn.dev/kutakutat/scraps/17884d66a25c02)。アクセストークンは有効期間が短く設計されており、`header`、`payload`、`署名`の3つの部分で構成されます[18](https://zenn.dev/kutakutat/scraps/17884d66a25c02), [6](https://zenn.dev/kutakutat/scraps/17884d66a25c02)。一方、リフレッシュトークンは期限切れになることはなく、一度しか使用できませんが、これを用いて新しいアクセストークンとリフレッシュトークンのペアを取得することが可能です[18](https://zenn.dev/kutakutat/scraps/17884d66a25c02), [6](https://zenn.dev/kutakutat/scraps/17884d66a25c02)。これらのトークンはブラウザ側のCookieに保存され、Supabaseクライアントは、このCookieと`anon_key`を組み合わせてSupabase APIにアクセスするように構成されています[18](https://zenn.dev/kutakutat/scraps/17884d66a25c02), [5](https://zenn.dev/kutakutat/scraps/17884d66a25c02), [7](https://zenn.dev/kutakutat/scraps/17884d66a25c02), [12](https://zenn.dev/kutakutat/scraps/17884d66a25c02)。
「Multiple GoTrueClient instances detected...」警告がセッションの未定義動作につながる可能性があるのは、複数のクライアントがそれぞれのストレージキーの下で独立してトークンを管理しようとするためだと考えられます。これにより、セッション情報の読み書きに競合が発生し、一方のクライアントが更新したセッションを他方のクライアントが認識せず、古いセッション情報に基づいてリクエストを送信したり、セッションが誤って破棄されたりする可能性が生じます。
Supabase Authは、認可コードフローとしてOAuth 2.0の拡張仕様であるPKCE(Proof Key for Code Exchange)を推奨しており、`signInWithOtp`、`signInWithOAuth`、`signUp`、`resetPasswordForEmail`などのメソッドでサポートされています[18](https://zenn.dev/kutakutat/scraps/17884d66a25c02), [13](https://zenn.dev/kutakutat/scraps/17884d66a25c02), [15](https://zenn.dev/kutakutat/scraps/17884d66a25c02), [19](https://zenn.dev/kutakutat/scraps/17884d66a25c02)。PKCEは、認可コードが横取りされた場合でも安全性を保つための重要な仕組みであり[18](https://zenn.dev/kutakutat/scraps/17884d66a25c02), [14](https://zenn.dev/kutakutat/scraps/17884d66a25c02), [16](https://zenn.dev/kutakutat/scraps/17884d66a25c02)、複数のGoTrueClientインスタンスがセッション管理に混乱をもたらすことは、PKCEのようなセキュリティ強化策の効果を損なうリスクもはらんでいます。
#### 対策と実践的な洞察
この警告に対処するための最も効果的な方法は、アプリケーション全体でSupabaseクライアントのインスタンスをシングルトンパターンで管理し、複数のインスタンスが生成されないようにすることです。特にNext.jsやNuxt.jsのようなフレームワークを使用している場合、公式が推奨する`@supabase/ssr`のようなヘルパーライブラリを活用し、クライアントの初期化を一元化することが重要です[18](https://zenn.dev/kutakutat/scraps/17884d66a25c02)。
例えば、Next.jsのApp RouterでSupabaseを使用する場合、以下のような構造でクライアントを生成することが推奨されています[8](https://zenn.dev/kutakutat/scraps/17884d66a25c02), [10](https://zenn.dev/kutakutat/scraps/17884d66a25c02)。
```javascript
// Server Component用
import { createServerClient, type CookieOptions } from '@supabase/ssr'
import { cookies } from 'next/headers'
export const createClient = (cookieStore: ReturnType<typeof cookies>) => {
return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
get(name: string) {
return cookieStore.get(name)?.value
},
set(name: string, value: string, options: CookieOptions) {
try {
cookieStore.set({ name, value, ...options })
} catch (error) {
// The `set` method was called from a Server Component.
// This can be ignored if you have middleware refreshing
// user sessions.
}
},
remove(name: string, options: CookieOptions) {
try {
cookieStore.set({ name, value: '', ...options })
} catch (error) {
// The `delete` method was called from a Server Component.
}
},
},
}
)
}
// Client Component用
import { createBrowserClient } from '@supabase/ssr'
export const createClient = () =>
createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
```
このように、用途に応じて単一のエントリポイントからクライアントを生成することで、複数のGoTrueClientインスタンスが意図せず作成されるのを防ぐことができます。また、Middlewareを利用してサーバーコンポーネントが読み込まれる前にトークンのリフレッシュを行うことも、セッション管理の安定化に寄与します[13](https://zenn.dev/kutakutat/scraps/17884d66a25c02)。
もしAIコーディングアプリ「Lovable」のユーザーのように[16](https://www.reddit.com/r/lovable/comments/1jcuton/getting_so_frustrated_with_lovable/?tl=ja)、この警告に起因する認証問題に直面している場合、まず上記の推奨されるクライアント作成方法を適用し、Supabaseの公式ドキュメント[18](https://supabase.com/docs/guides/auth/server-side/creating-a-client?environment=client-component)を参照して最新のベストプラクティスに従うことが重要です。特に、古いバージョンのライブラリを使用している場合は、最新の`@supabase/ssr`への移行を検討することで、インスタンス管理の改善とそれに伴う問題の解決が期待できます。
🖍 考察
### 調査の本質
ユーザーが遭遇した「Multiple GoTrueClient instances detected in the same browser context.」という警告メッセージは、Supabase Auth(GoTrueClient)が同一ブラウザコンテキスト内で複数回初期化され、同じストレージキーを同時に操作しようとしていることを示しています[1](https://www.reddit.com/r/Nuxt/comments/15f5wzo/error_multiple_gotrueclient_instances_detected_in/)。
真のニーズは、**認証セッションの安定性を確保**し、予期せぬ未定義動作(セッションの即時破棄やリダイレクトなど)を防ぐことです。多くの開発時間を無駄にせず、堅牢なユーザー体験を提供するために、クライアントインスタンスの適切な管理と一元化が求められています。
### 分析と発見事項
1. フレームワーク依存:
- **Next.js(App Router)**/**Nuxt.js** などのモダンJSフレームワークでは、`useSupabaseClient()`や`createClient`を複数箇所で呼び出すと警告が発生しやすい[1](https://www.reddit.com/r/Nuxt/comments/15f5wzo/error_multiple_gotrueclient_instances_detected_in/)。
2. バージョンとライブラリの変化:
- 以前は`@supabase/auth-helpers-nextjs`が5種類のクライアント生成関数を提供していたが、最新版のβ版`@supabase/ssr`では「2種類」に集約され、重複生成リスクを軽減している[18](https://zenn.dev/kutakutat/scraps/17884d66a25c02)。
3. 環境差異:
- Vercelのプレビュー環境では、ログイン直後にセッションが削除されリダイレクトされる事象が報告されているが、本番環境では正常動作する[5](https://community.vercel.com/t/session-handling-in-v0-previews/6527)。これはプレビュー/本番でのCookie設定や内部最適化の差異を示唆する。
4. セッション管理の相関:
- 複数インスタンスがCookieやローカルストレージのJWTアクセストークン/リフレッシュトークンを同時に読書きしようとすると、競合により認証状態が不安定化する。
### より深い分析と解釈
1. なぜ複数インスタンスが生成されるか?
- 各コンポーネント/ルートで`createClient`やフックを直書きし、中央管理されていないため。
2. なぜ中央管理がされていないか?
- 旧ライブラリ時代のサンプルコードに倣い、場当たり的な初期化を行っている。新ライブラリへの移行が追いついていない。
3. なぜ移行が進まないか?
- `@supabase/ssr`がβ版であることへの抵抗感や、既存コードの改修コストを懸念しているため。
代替解釈として、Vercelプレビュー固有のキャッシュ・最適化処理がSSR/CSRの切り替えと衝突している可能性も考えられます。また、`Secure`属性や`sameSite`などCookieの細かな設定差異がセッション継続に影響しているケースも否定できません。
### 戦略的示唆
**短期的対応**
1. クライアント生成をユーティリティモジュールに集約し、シングルトンパターンを徹底する。
2. Next.jsであれば`@supabase/ssr`の`createBrowserClient`/`createServerClient`を1箇所に定義しインポートして利用する[18](https://zenn.dev/kutakutat/scraps/17884d66a25c02)。
3. Vercelプレビュー環境では、Cookieの`secure`属性を開発用に`false`、本番用に`true`で切り替える設定を追加する[2](https://zenn.dev/kutakutat/scraps/17884d66a25c02)。
**中長期的戦略**
- 全プロジェクトで`@supabase/ssr`への移行を完了し、旧`auth-helpers-nextjs`を廃止。
- Nuxt3では専用プラグインを作成し、`useSupabaseClient`をラップして単一インスタンスを提供。
- 認証ミドルウェアを導入し、リクエストごとにセッションをリフレッシュして安定化させる。
**リスク管理とモニタリング**
- 「Multiple GoTrueClient」警告をログ集約ツールで検出し、アラートを設定。
- 定期的にSupabaseライブラリの更新情報をレビューし、クライアント生成ロジックを見直す。
### 今後の調査の提案
- Next.js + Supabase SSR移行のベストプラクティス検証
- Nuxt3環境におけるSupabaseクライアント一元管理プラグインの設計
- Vercelプレビュー環境と本番環境のCookie/セッション管理差異の詳細調査
- Supabase Auth のCookie属性(sameSite, secure, httpOnly)最適設定ガイドライン策定
- PKCEフロー実装の安全性および脆弱性検証
- AIコーディングツール(Lovable等)生成コードに潜む認証脆弱性の分析
- 継続的モニタリング:警告検出→自動アラートシステム開発
📚 参考文献
参考文献の詳細は、ブラウザでページを表示してご確認ください。