mckaywrigley/chatbot-ui · error
Error downloading message image
Error message
Error downloading message image
What it means
Thrown by getMessageImageFromStorage when createSignedUrl(filePath, 86400) on the 'message_images' bucket returns an error. Supabase fails signed-url creation when the object doesn't exist at filePath or the caller's role can't SELECT it. Unlike getAssistantImageFromStorage, this version throws to the caller rather than swallowing the error.
Solutions
- Verify the object exists at the logged path in the Supabase storage dashboard.
- Add a storage.objects SELECT policy on message_images for authenticated users (or make the bucket public if appropriate).
- Wrap the call and fall back to a placeholder image when signing fails, so one bad message doesn't break the whole chat render.
- Audit for code paths that delete message images while messages still reference them.
Example fix
// before
const url = await getMessageImageFromStorage(path)
// after
let url: string | null = null
try {
url = await getMessageImageFromStorage(path)
} catch {
url = null // render placeholder
} Defensive patterns
Strategy: fallback
Validate before calling
if (!filePath) return placeholderUrl
Type guard
const isSignablePath = (p: unknown): p is string =>
typeof p === "string" && p.length > 0 && !p.startsWith("/") Try / catch
let url: string | null = null
try {
url = await getMessageImageFromStorage(path)
} catch {
url = null // render image placeholder in the chat bubble
} Prevention
- Never render message history without guarding signed-url failures — one missing object shouldn't break the thread.
- Keep SELECT policies on message_images aligned with who may view messages.
- Re-sign URLs on demand; never cache them beyond their 24h validity.
When it happens
Trigger: Loading a chat message whose image path was deleted from storage, was written to a different bucket/project, or isn't covered by a storage.objects SELECT policy for the current (possibly anon) role; passing an empty or malformed path string.
Common situations: Old messages referencing purged objects (retention jobs, manual bucket cleanup); private bucket without SELECT policies; rendering history while logged out where anon role can't read; environment mismatch between DB rows and storage bucket contents.
Related errors
- Error downloading assistant image
- Error downloading file
- Error uploading image
- Error deleting old image
- Error uploading file
AI-assisted analysis of mckaywrigley/chatbot-ui@81328b61d2 (2026-08-27).
Data as JSON: /api/errors/9942000d803b4887.
Report an issue: GitHub.
Appendix: source
Thrown at db/storage/message-images.ts:29
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)