SuperAPI AI 工具集

supabase-common-errors

编程与开发

查看项目

更新于 10-16 09:10

技能介绍

概述

Supabase Common Errors 是一个针对 Supabase 错误的分层诊断指南,覆盖 PostgREST(PGRST*)、PostgreSQL(数字错误码)、Auth、Storage 和 Realtime 五个子系统。目标是帮助定位错误所在层级、追溯根因并应用正确修复方式。关键前提:SDK 的每次调用都会返回 { data, error } 元组,当 error 存在时 data 为 null。

工作流分三步:捕获错误对象、按层级和错误码分类、应用并验证修复。完整的逐步代码位于诊断演练中,完整速查表位于错误参考中。

先决条件

  • 已安装 @supabase/supabase-js(npm install @supabase/supabase-js)
  • 已配置 SUPABASE_URL 和 SUPABASE_ANON_KEY(或 SUPABASE_SERVICE_ROLE_KEY)
  • 可访问 Supabase Dashboard(用于查看日志和 SQL Editor)
  • 本地开发需安装 Supabase CLI(npx supabase --version)

使用方式

第一步 — 捕获错误对象

不要假定 data 一定存在,应先解构并检查 error。当 error 存在时 data 为 null。

const { data, error } = await supabase.from('todos').select('*')
if (error) {
  console.error(`[${error.code}] ${error.message}`)
  return  // data is null here — do not touch it
}
console.log(`Found ${data.length} rows`)

如果 error 是 undefined 而不是 null,请升级到 @supabase/supabase-js@2.x。

第二步 — 识别错误层级与错误码

按错误码前缀匹配子系统:

  • PGRST* → PostgREST(API 网关:JWT、查询解析、schema)
  • 5 位数字(如 42501、23505)→ PostgreSQL 引擎(RLS、约束、迁移)
  • AuthApiError → Auth 服务(凭证、确认、令牌过期)
  • StorageApiError → Storage 服务(bucket、storage.objects 上的 RLS、大小限制)

缺少错误码时通常看 HTTP 状态:401 → SUPABASE_ANON_KEY 错误或缺失;500 → 数据库函数中未处理的异常。

第三步 — 应用修复并验证

应用对应速查表中的修复后,重新执行原操作确认。常见恢复手段:

  • 用 supabase.auth.refreshSession() 刷新过期的 JWT(PGRST301)。
  • 用 service-role 客户端重新查询以确认 RLS 拦截(42501),再修正策略。
  • 迁移后重载 PostgREST schema 缓存(Dashboard → Settings → API → "Reload schema cache",或 NOTIFY pgrst, 'reload schema')。

输出

应用本技能后的交付物:

  • 按错误码和层级识别的错误(PostgREST、PostgreSQL、Auth、Storage、Realtime)
  • 通过诊断辅助工具或人工代码检查定位根因
  • 已从错误处理表应用修复,并针对原失败操作验证
  • 已加入守卫代码(if (error) 检查),防止静默的 null-data 缺陷

错误处理速查

PostgREST API 错误(PGRST*)

错误码 HTTP 含义 根因 修复
PGRST301 401 JWT 过期或无效 SUPABASE_ANON_KEY 错误,或用户会话过期 验证 SUPABASE_ANON_KEY 与项目匹配;调用 supabase.auth.refreshSession()
PGRST302 401 缺少 Authorization 头 客户端创建时未带 key,或中间件剥离了头 向 createClient() 传入 SUPABASE_ANON_KEY;检查代理/CDN 配置
PGRST116 406 .single() 未返回行 查询匹配 0 行但 .single() 期望恰好 1 行 可选查询用 .maybeSingle(),或检查过滤条件
PGRST200 400 无效查询参数 过滤格式错误、运算符错误或列引用无效 检查过滤语法:.eq('col', val) 而非 .eq('col = val')
PGRST204 400 列不存在 表或视图中不存在该列名 用 supabase gen types typescript 验证列是否存在;检查拼写
PGRST000 503 连接池耗尽 来自 serverless 函数的并发连接过多 在项目设置中启用 pgBouncer(Supavisor);减少连接数

PostgreSQL 数据库错误(5 位数字码)

错误码 含义 根因 修复
42501 RLS 策略违规 行级安全策略阻止了该用户的操作 添加或修正 RLS 策略;用 service role 测试确认
23505 唯一约束冲突 INSERT/UPDATE 与已有行冲突 使用 .upsert({ onConflict: 'column' }) 或先检查存在性
23503 外键违规 父表中不存在被引用的行 先插入父行,或检查外键值
42P01 表或关系不存在 迁移未应用,或 schema 错误 运行 supabase db push;在 SQL Editor 中用 \dt 验证 schema
42703 列不存在 schema 与代码不同步 重新生成类型:supabase gen types typescript --local > types/supabase.ts
57014 查询被取消(语句超时) 查询耗时超过 statement_timeout 添加索引;简化查询;在 postgresql.conf 中增大超时

示例

对可选数据调用 .single()(PGRST116)

// BAD — throws PGRST116 when the user has no profile row
const { data: profile } = await supabase
  .from('profiles').select('*').eq('user_id', userId).single()

// GOOD — returns null instead of erroring
const { data: profile, error } = await supabase
  .from('profiles').select('*').eq('user_id', userId).maybeSingle()

if (!profile) {
  await supabase.from('profiles').insert({ user_id: userId, display_name: 'New User' })
}

更多示例(用 upsert 规避 23505、Realtime 订阅错误处理、serverless 连接池耗尽)位于示例参考中。

适用场景

  • 开发中遇到 Supabase 返回的错误码需要快速定位层级与根因
  • 排查 RLS、约束冲突、迁移未应用等数据库层问题
  • 处理 JWT 过期、schema 缓存未刷新等 API 层问题
  • 为代码加入 error 守卫,避免静默 null-data 缺陷

限制

  • 资料仅覆盖 PostgREST、PostgreSQL、Auth、Storage、Realtime 的错误处理;完整 Auth、Storage、Realtime 错误表未在本文展开,需参考完整错误参考。
  • 未提供官方文档原文,部分链接与延伸资源(诊断演练、错误参考、示例参考、SDK 文档、状态页等)仅以资料中名称列出。
  • Auth、Storage、Realtime 的具体错误码与修复步骤暂未提供。

后续步骤

  • 若修复后错误仍存在,使用 supabase-debug-bundle 生成完整诊断快照。
  • 使用 supabase-security-basics 审计 RLS 策略,主动预防 42501 错误。
  • 使用 supabase-known-pitfalls 了解可能导致隐蔽缺陷的边界情况和 SDK 行为。
  • 使用 supabase-observability 设置日志和告警,在用户报告前捕获错误。