mckaywrigley/chatbot-ui · error · Error

error.message

Error message

error.message

What it means

getAssistantById selects a single assistants row by id and throws error.message when no data returns. Because the guard is on !assistant rather than error, a not-found id (where error is null) crashes with 'Cannot read properties of null' instead of a clean message, and genuine query errors (RLS, connection) surface their raw message.

Source

Thrown at db/assistants.ts:12

import { supabase } from "@/lib/supabase/browser-client"
import { TablesInsert, TablesUpdate } from "@/supabase/types"

export const getAssistantById = async (assistantId: string) => {
  const { data: assistant, error } = await supabase
    .from("assistants")
    .select("*")
    .eq("id", assistantId)
    .single()

  if (!assistant) {
    throw new Error(error.message)
  }

  return assistant
}

export const getAssistantWorkspacesByWorkspaceId = async (
  workspaceId: string
) => {
  const { data: workspace, error } = await supabase
    .from("workspaces")
    .select(
      `
      id,
      name,
      assistants (*)
    `
    )
    .eq("id", workspaceId)

View on GitHub (pinned to 81328b61d2)

Solutions

  1. Check error before data and model 'not found' explicitly (return null or throw a NotFound error)
  2. Validate the id is a UUID before querying
  3. Confirm the RLS SELECT policy allows the requesting user
  4. Cache/verify existence at the API layer before dereferencing

Example fix

// before
if (!assistant) {
  throw new Error(error.message)
}

// after
if (error) throw new Error(`getAssistantById failed: ${error.message}`)
if (!assistant) throw new NotFoundError(`Assistant ${assistantId} not found`)
// or: return null
Defensive patterns

Strategy: type-guard

Validate before calling

const isUuid = (id: string) => /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id)
if (!isUuid(assistantId)) return notFound()

Type guard

const isAssistant = (x: unknown): x is { id: string; user_id: string } =>
  !!x && typeof x === 'object' && typeof (x as any).id === 'string'

Try / catch

try { const a = await getAssistantById(id); if (!a) return notFound() } catch (e) { if (e instanceof TypeError) return notFound(); throw e }

Prevention

When it happens

Trigger: Looking up a deleted or never-existing assistantId; RLS SELECT policy hiding the row; invalid UUID string; Supabase project unreachable returning a fetch error.

Common situations: Stale assistant IDs in URLs after deletion; cross-workspace access blocked by RLS; deep links shared between users; test fixtures wiped between runs.

Related errors


AI-assisted analysis of mckaywrigley/chatbot-ui@81328b61d2 (2026-08-27). Data as JSON: /api/errors/5098f4f23f0d4f79. Report an issue: GitHub.