mckaywrigley/chatbot-ui · error · Error
error.message
Error message
error.message
What it means
Thrown by `getPresetById` when `.single()` returns no row — the code checks `if (!preset)` and throws `error.message`, which for a missing row is PGRST116 ("JSON object requested, multiple (or no) rows returned") or a null message. It conflates 'not found' with genuine query failures because it tests the data, not the error object.
Source
Thrown at db/presets.ts:12
import { supabase } from "@/lib/supabase/browser-client"
import { TablesInsert, TablesUpdate } from "@/supabase/types"
export const getPresetById = async (presetId: string) => {
const { data: preset, error } = await supabase
.from("presets")
.select("*")
.eq("id", presetId)
.single()
if (!preset) {
throw new Error(error.message)
}
return preset
}
export const getPresetWorkspacesByWorkspaceId = async (workspaceId: string) => {
const { data: workspace, error } = await supabase
.from("workspaces")
.select(
`
id,
name,
presets (*)
`
)
.eq("id", workspaceId)
.single()
View on GitHub (pinned to 81328b61d2)
Solutions
- Check `error` first and treat code PGRST116 / null preset as a typed NotFound case
- Verify the preset id exists with the same role/credentials the app uses
- If an embedded relation is selected, ensure the FK and relation name are valid
- Return null or a domain-specific NotFoundError instead of throwing raw error.message
Example fix
// before
if (!preset) throw new Error(error.message)
// after
if (error) throw new Error(`getPresetById failed (${error.code}): ${error.message}`)
if (!preset) throw new NotFoundError(`Preset ${presetId} not found`)
// or: return preset ?? null and let callers handle absence Defensive patterns
Strategy: type-guard
Validate before calling
const isUuid = (v: string) => /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v)
if (!isUuid(presetId)) return null Type guard
const isPreset = (x: unknown): x is Preset => typeof x === "object" && x !== null && "id" in x && "user_id" in x
Try / catch
try {
return await getPresetById(presetId)
} catch (e) {
const msg = String(e?.message ?? e)
if (msg.includes("0 rows") || msg.includes("PGRST116")) return null // not found is not exceptional
throw e
} Prevention
- Use .maybeSingle() and return null for optional lookups instead of .single() throwing
- Validate route params as uuids before fetching
- Expect RLS to hide other users' presets — design UI for 'not found'
When it happens
Trigger: Fetching a preset id that doesn't exist, was deleted, or is filtered out by row-level security for the current user; also fires on genuine query errors (bad column in select, network failure) since only `preset` is checked.
Common situations: Deep links to a removed preset, stale ids in client cache, RLS hiding other users' presets, or a typo in the `select("*")` / embedded relation string causing PostgREST to error with null data.
Related errors
AI-assisted analysis of mckaywrigley/chatbot-ui@81328b61d2 (2026-08-27).
Data as JSON: /api/errors/63bcccf1472e517c.
Report an issue: GitHub.