mckaywrigley/chatbot-ui · error
Error uploading image
Error message
Error uploading image
What it means
Thrown by uploadAssistantImage when supabase.storage.from("assistant_images").upload(filePath, image, { upsert: true }) returns an error. Supabase Storage returns errors such as 'Bucket not found', 'Duplicate' (when upsert can't overwrite), 'row-level security violation', or 'Payload too large' — all collapsed into this generic message. The file is never stored and the function aborts before returning the new path.
Source
Thrown at db/storage/assistant-images.ts:36
if (currentPath.length > 0) {
const { error: deleteError } = await supabase.storage
.from(bucket)
.remove([currentPath])
if (deleteError) {
throw new Error("Error deleting old image")
}
}
const { error } = await supabase.storage
.from(bucket)
.upload(filePath, image, {
upsert: true
})
if (error) {
throw new Error("Error uploading image")
}
return filePath
}
export const getAssistantImageFromStorage = async (filePath: string) => {
try {
const { data, error } = await supabase.storage
.from("assistant_images")
.createSignedUrl(filePath, 60 * 60 * 24) // 24hrs
if (error) {
throw new Error("Error downloading assistant image")
}
return data.signedUrl
} catch (error) {
console.error(error)View on GitHub (pinned to 81328b61d2)
Solutions
- Log the underlying error object — its message ('Bucket not found', 'row-level security policy', 'Duplicate') identifies the exact cause.
- Create the 'assistant_images' bucket if missing and add INSERT + UPDATE (for upsert) policies scoped to auth.uid() = (storage.foldername(name))[1].
- Ensure the user is authenticated (valid Supabase session) before calling uploadAssistantImage — refresh the session if the JWT is stale.
- Verify NEXT_PUBLIC_SUPABASE_URL / ANON_KEY env vars point at the project that has the bucket.
Example fix
// before
if (error) {
throw new Error("Error uploading image")
}
// after
if (error) {
throw new Error(`Error uploading image: ${error.message}`)
} Defensive patterns
Strategy: retry
Validate before calling
const { data: session } = await supabase.auth.getSession()
if (!session.session) {
throw new Error("Sign in before uploading an assistant image")
} Type guard
const isStorageError = (e: unknown): e is { message: string; statusCode?: string } =>
typeof e === "object" && e !== null && "message" in e Try / catch
let lastErr: unknown
for (let attempt = 0; attempt < 3; attempt++) {
const { error } = await supabase.storage.from("assistant_images").upload(path, image, { upsert: true })
if (!error) break
lastErr = error
if (!/network|fetch|timeout/i.test(error.message)) break // only retry transient errors
await new Promise(r => setTimeout(r, 500 * 2 ** attempt))
} Prevention
- Verify the bucket and INSERT/UPDATE policies exist before shipping each environment.
- Refresh expired sessions before storage writes.
- Preserve error.message when rethrowing so RLS vs bucket issues are diagnosable.
When it happens
Trigger: Uploading an image whose object key user_id/assistant_id/timestamp violates a storage INSERT/UPDATE policy; bucket 'assistant_images' doesn't exist in the project; session expired so the anon JWT fails the policy; image content-type rejected; or Supabase's global 50MB object cap hit (unlikely at the 6MB app limit).
Common situations: Missing or wrong storage.objects policies after creating the bucket via dashboard; using the anon key client-side while policies require owner; supabase URL/keys env vars misconfigured per environment; expired auth session in a long-lived browser tab.
Related errors
- Error deleting old image
- Error uploading file
- Error uploading image
- Error downloading assistant image
- error.message
AI-assisted analysis of mckaywrigley/chatbot-ui@81328b61d2 (2026-08-27).
Data as JSON: /api/errors/1e5cc8c89cbec920.
Report an issue: GitHub.