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

  1. Check `error` first and treat code PGRST116 / null preset as a typed NotFound case
  2. Verify the preset id exists with the same role/credentials the app uses
  3. If an embedded relation is selected, ensure the FK and relation name are valid
  4. 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

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.