Next.js中NEXT_PUBLIC变量异常致Supabase 403错误排查
问题背景
基于Next.js开发Supabase应用时遇到异常:所有通过@supabase/supabase-js的createClient()发起的请求均返回403 Forbidden,提示“Invalid API key”,但同一密钥在浏览器控制台用fetch()直接调用Supabase API却能正常返回数据。
配置与代码
.env.local配置:
NEXT_PUBLIC_SUPABASE_URL=https://rgfqebiuevnwfetdfaoh.supabase.co NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...
lib/supabase.ts初始化代码:
import { createClient } from '@supabase/supabase-js' export const supabase = createClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! )
已尝试的排查步骤
- 确认
.env.local在项目根目录,NEXT_PUBLIC_前缀正确 - 多次重启开发服务,终端打印环境变量显示正常
- 硬编码URL和密钥到
createClient(),问题依旧 - 禁用表RLS、验证RLS策略、用anon角色执行直接SQL查询均正常
- 尝试旧版JWT密钥和新版可发布密钥
- 部署到Netlify后问题未解决
版本信息
- Next.js 16.2.6
- @supabase/supabase-js 2.106.1
- pnpm 11.1.3
- Node v24.11.1
可能的原因与解决方法
1. Supabase-js请求头格式或全局拦截问题
Supabase-js默认会将anon key放在Authorization: Bearer <key>请求头中,而你用fetch()测试时可能使用的是apikey查询参数(比如https://<project>.supabase.co/rest/v1/table?apikey=<your-key>)。
排查与修复:
- 打开浏览器开发者工具Network面板,查看Supabase-js发起的请求的
Authorization头,确认密钥完整无截断,格式为Bearer <你的完整anon key> - 若差异在于参数传递方式,可强制Supabase-js使用查询参数传递密钥:
export const supabase = createClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, { global: { headers: { apikey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! } } } )
2. Next.js App Router与Supabase-js初始化时机冲突
Next.js 16的App Router对客户端组件的状态管理和实例初始化有严格要求,全局导出的supabase实例可能因hydration或生命周期问题导致请求异常。
解决方法:
改用@supabase/ssr包的createBrowserClient专门初始化浏览器端实例,避免全局实例问题:
- 安装依赖:
pnpm add @supabase/ssr - 修改
lib/supabase.ts:import { createBrowserClient } from '@supabase/ssr' export const createSupabaseClient = () => createBrowserClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! ) - 在客户端组件中动态创建实例:
'use client' import { createSupabaseClient } from '@/lib/supabase' export default function MyComponent() { const supabase = createSupabaseClient() // 后续使用supabase实例发起请求 return <div>...</div> }
3. 版本兼容性问题
Supabase-js 2.106.1是较新版本,可能与Next.js 16存在未适配的兼容性问题。
解决方法:
降级Supabase-js到稳定版本,比如2.99.3:
pnpm add @supabase/supabase-js@2.99.3
4. 全局Fetch被修改
Next.js 16默认会对fetch进行增强(缓存、重试等),若项目中有全局配置或第三方库修改了fetch行为,可能影响Supabase-js的请求。
排查步骤:
- 检查
next.config.js中的experimental.fetchCache或headers配置,是否有覆盖请求头的设置 - 排查是否有第三方库(如axios拦截器、身份验证库)修改了全局
fetch或请求头
内容的提问来源于stack exchange,提问作者Muchi Bari

