You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Supabase开启RLS后查询返回406 JSON object requested错误

Supabase开启RLS后查询返回406错误解决方案

问题现象

  • 已查阅StackOverflow、Supabase相关GitHub仓库(supabase/postgrest-js、PostgREST/postgrest)的issue,也检索了Discord社区相关讨论,现有公开方案均未生效。
  • RLS(行级安全)关闭时代码运行完全符合预期,开启RLS后查询返回406错误。

测试代码

export const supabase = createClient(process.env.NEXT_PUBLIC_SUPABASE_URL, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY)

const { data, error } = await supabase.from('profiles').select('*').eq('id', userId).maybeSingle()
// 以下两种写法在RLS关闭时均可正常运行
// const { data, error } = await supabase.from('profiles').select('*').eq('id', userId).limit(1).single()
// const { data, error } = await supabase.from('profiles').select('*').eq('id', userId).single()

响应对比

RLS关闭时正常返回数据:

{
    "id": "123-123-1241-1231",
    "created_at": "2022-06-10T03:59:22.751125+00:00",
    "is_subscribed": false,
    "interval": null,
    "email": "test@example.com"
}

RLS开启后返回错误:

{
    "message": "请求JSON对象格式响应,但返回了多行(或零行)结果",
    "details": "结果包含0行数据,application/vnd.pgrst.object+json类型要求必须返回1行数据"
}

已尝试操作

  • 重载schema、重新编写安全策略,问题未解决
  • profiles表id字段关联auth.users.id,最初安全策略针对anon角色配置,后尝试将目标角色改为authenticated,策略规则为:
    (uid() = id)
    
  • 尝试将原表名profile改为复数形式profiles,问题依然存在

根因分析

这个错误和查询写法、表名、schema缓存无关,RLS关闭时查询正常已经证明语法完全正确,核心原因是RLS策略拦截了查询,当前请求身份没有权限读取目标行,数据库实际返回了0行结果。

按以下优先级排查修复即可:

  • 检查请求携带的身份凭证是否有效
    策略规则(uid() = id)生效的前提是uid()能正确获取到当前登录用户ID:
    • 客户端侧请求:必须先完成Supabase登录流程(邮箱密码、第三方OAuth等),未登录状态下请求走匿名身份,uid()返回null,永远无法匹配到对应ID的行
    • Next.js服务端组件/路由处理程序中发起请求:仅用公网可获取的anon key初始化客户端拿不到用户登录态,必须从请求Cookie/头信息中提取当前用户的认证token注入Supabase客户端,否则服务端请求默认使用匿名身份,会被RLS直接拦截
  • 检查RLS策略配置正确性
    进入Supabase后台策略编辑页逐项确认:
    1. 为profiles表的SELECT操作单独配置策略,不要和INSERT/UPDATE等操作共用策略导致漏选SELECT权限
    2. 策略生效角色仅勾选authenticated即可,不要给anon(未登录匿名用户)角色配置用户私有表的访问权限,避免数据泄露
    3. 策略规则直接使用id = auth.uid()即可,无需额外加其他过滤条件
  • 验证策略实际执行效果
    打开Supabase内置SQL编辑器,执行以下语句模拟认证用户查询,直接在数据库层验证策略是否生效:
    -- 替换为你实际测试的用户UUID
    SET request.jwt.claim.sub = '123-123-1241-1231';
    SET ROLE authenticated;
    -- 执行查询看是否能返回目标数据
    SELECT * FROM profiles WHERE id = '123-123-1241-1231';
    
    如果上述语句依然返回空结果,检查表结构配置:
    • 确认profiles.id字段类型为uuid,和auth.users.id字段类型完全一致,类型不匹配会导致等值判断失效
    • 确认profiles表中确实存在对应用户ID的记录,没有因为注册触发器未生效、手动操作等原因缺失用户profile行

内容的提问来源于stack exchange,提问作者Scott Yu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 07:15:40