mckaywrigley/chatbot-ui · error · Error

error.message

Error message

error.message

What it means

getChatFilesByChatId selects a single row of chat files by chat id and throws error.message when no data returns. The !chatFiles guard treats an empty result as an error, but on empty results error is null, so the actual exception is 'Cannot read properties of null (reading message)' — masking the true not-found condition.

Source

Thrown at db/chat-files.ts:18

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

export const getChatFilesByChatId = async (chatId: string) => {
  const { data: chatFiles, error } = await supabase
    .from("chats")
    .select(
      `
      id, 
      name, 
      files (*)
    `
    )
    .eq("id", chatId)
    .single()

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

  return chatFiles
}

export const createChatFile = async (chatFile: TablesInsert<"chat_files">) => {
  const { data: createdChatFile, error } = await supabase
    .from("chat_files")
    .insert(chatFile)
    .select("*")

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

  return createdChatFile
}

View on GitHub (pinned to 81328b61d2)

Solutions

  1. Check error before data; return null or an empty structure when the chat simply has no files
  2. Verify the chat exists and the caller can read chat_files under RLS
  3. Validate the chatId format before querying
  4. Ensure the chat_files table/view is migrated in this environment

Example fix

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

// after
if (error) throw new Error(`getChatFilesByChatId failed: ${error.message}`)
if (!chatFiles) return { chatId, files: [] } // or null
Defensive patterns

Strategy: type-guard

Validate before calling

const isUuid = (id: string) => /^[0-9a-f-]{36}$/i.test(id)
if (!isUuid(chatId)) return { files: [] }

Type guard

const hasFiles = (x: unknown): x is { files: unknown[] } =>
  !!x && typeof x === 'object' && Array.isArray((x as any).files)

Try / catch

try { const r = await getChatFilesByChatId(chatId); if (!r) return [] } catch (e) { if (e instanceof TypeError) return []; throw e }

Prevention

When it happens

Trigger: Chat id with no chat_files row (new chat, no uploads yet); RLS SELECT policy hiding the row; invalid chat id; relation missing after schema drift.

Common situations: Opening a chat before any file is attached; member role without SELECT policy coverage; environment missing the chat_files view/table.

Related errors


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