mckaywrigley/chatbot-ui · error
Error uploading image
Error message
Error uploading image
What it means
Thrown by uploadMessageImage when supabase.storage.from("message_images").upload(path, image, { upsert: true }) returns an error. The StorageError's real message (bucket not found, RLS violation, duplicate, size/type rejection) is masked by this generic string. Because upsert is enabled, an existing object at the same path must be updatable, not just insertable.
Source
Thrown at db/storage/message-images.ts:17
import { supabase } from "@/lib/supabase/browser-client"
export const uploadMessageImage = async (path: string, image: File) => {
const bucket = "message_images"
const imageSizeLimit = 6000000 // 6MB
if (image.size > imageSizeLimit) {
throw new Error(`Image must be less than ${imageSizeLimit / 1000000}MB`)
}
const { error } = await supabase.storage.from(bucket).upload(path, image, {
upsert: true
})
if (error) {
throw new Error("Error uploading image")
}
return path
}
export const getMessageImageFromStorage = async (filePath: string) => {
const { data, error } = await supabase.storage
.from("message_images")
.createSignedUrl(filePath, 60 * 60 * 24) // 24hrs
if (error) {
throw new Error("Error downloading message image")
}
return data.signedUrl
}
View on GitHub (pinned to 81328b61d2)
Solutions
- Log the error object to surface error.message ('Bucket not found', 'row-level security', 'Duplicate').
- Create the 'message_images' bucket and grant INSERT + UPDATE policies to the object owner (auth.uid() = (storage.foldername(name))[1]).
- Ensure the user has a fresh authenticated session before uploading.
- Confirm the client is pointed at the project containing the bucket (check NEXT_PUBLIC_ env vars).
Example fix
// before
if (error) {
throw new Error("Error uploading image")
}
// after
if (error) {
throw new Error(`Error uploading image to message_images: ${error.message}`)
} Defensive patterns
Strategy: retry
Validate before calling
const { data: s } = await supabase.auth.getSession()
if (!s.session) throw new Error("Sign in before sending images") Type guard
const isUploadedImage = (r: unknown): r is string => typeof r === "string" && r.length > 0
Try / catch
for (let i = 0; i < 3; i++) {
const { error } = await supabase.storage.from("message_images").upload(path, image, { upsert: true })
if (!error) break
if (!/network|fetch|timeout/i.test(error.message)) throw new Error(error.message)
await new Promise(r => setTimeout(r, 400 * 2 ** i))
} Prevention
- Ship bucket + policy creation in a setup migration so every environment has 'message_images'.
- Grant both INSERT and UPDATE policies since upsert: true requires both.
- Guard uploads with an active session check.
When it happens
Trigger: The 'message_images' bucket doesn't exist in the project; the caller's role fails an INSERT or UPDATE storage policy for the given path; session expired so requests run as anon; or the path collides with an object owned by another user and upsert is denied.
Common situations: Bucket created in dev but not prod (or vice versa); storage policies only granting INSERT so upsert-overwrite fails with 'Duplicate'; missing auth session refresh in long-lived tabs; wrong supabase project env vars after forking the app.
Related errors
- Error uploading image
- Error uploading file
- Error deleting old image
- Error downloading message image
- error.message
AI-assisted analysis of mckaywrigley/chatbot-ui@81328b61d2 (2026-08-27).
Data as JSON: /api/errors/19ef97d088dbb37d.
Report an issue: GitHub.