mckaywrigley/chatbot-ui · error · Error
error.message
Error message
error.message
What it means
getAssistantFilesByAssistantId selects a single row from a view/table keyed by assistant id and throws error.message when no data comes back. Because the code checks !assistantFiles rather than error, this throws even when the query legitimately returns zero rows — and in that case error is null, so error.message throws 'Cannot read properties of null' instead. It conflates 'not found' with 'query failed'.
Source
Thrown at db/assistant-files.ts:18
import { supabase } from "@/lib/supabase/browser-client"
import { TablesInsert } from "@/supabase/types"
export const getAssistantFilesByAssistantId = async (assistantId: string) => {
const { data: assistantFiles, error } = await supabase
.from("assistants")
.select(
`
id,
name,
files (*)
`
)
.eq("id", assistantId)
.single()
if (!assistantFiles) {
throw new Error(error.message)
}
return assistantFiles
}
export const createAssistantFile = async (
assistantFile: TablesInsert<"assistant_files">
) => {
const { data: createdAssistantFile, error } = await supabase
.from("assistant_files")
.insert(assistantFile)
.select("*")
if (!createdAssistantFile) {
throw new Error(error.message)
}
return createdAssistantFileView on GitHub (pinned to 81328b61d2)
Solutions
- Distinguish the two cases: check error first, then treat null data as 'not found' and return null or throw a dedicated NotFoundError
- Verify the assistantId exists and the current user's RLS SELECT policy covers assistant_files
- Validate assistantId is a UUID before querying
- Re-run the query in the Supabase table editor to see whether the row is visible to your role
Example fix
// before
if (!assistantFiles) {
throw new Error(error.message)
}
// after
if (error) throw new Error(`getAssistantFiles failed: ${error.message}`)
if (!assistantFiles) return null // or throw new NotFoundError(`No files for assistant ${assistantId}`) 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)) throw new Error('invalid assistantId') Type guard
const hasFiles = (x: unknown): x is { files: unknown[] } =>
!!x && typeof x === 'object' && Array.isArray((x as any).files) Try / catch
try { const files = await getAssistantFilesByAssistantId(id) } catch (e) { if (e instanceof TypeError) return [] /* not-found path */ throw e } Prevention
- Treat null data as empty, not exceptional
- Patch the library to check error before data
- Cache file lists per assistant to avoid repeated lookups
When it happens
Trigger: Passing an assistantId that has no files row (error is null → TypeError reading 'message'); an RLS SELECT policy hiding the row from the current user; a malformed UUID for id causing a PostgREST 22P02 invalid-input error.
Common situations: Fetching an assistant created before the assistant_files row existed; RLS enabled without a SELECT policy; integration tests using random IDs; .single() on an empty result set.
Related errors
AI-assisted analysis of mckaywrigley/chatbot-ui@81328b61d2 (2026-08-27).
Data as JSON: /api/errors/c53a32a4335ba9f8.
Report an issue: GitHub.