mckaywrigley/chatbot-ui · error
Error downloading assistant image
Error message
Error downloading assistant image
What it means
Thrown by getAssistantImageFromStorage when createSignedUrl(filePath, 86400) on the assistant_images bucket returns an error. Signed-url creation fails server-side when the object at filePath doesn't exist or the caller can't SELECT it. Note the surrounding try/catch swallows the error and returns undefined, so callers see a missing URL rather than the throw.
Source
Thrown at db/storage/assistant-images.ts:49
.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
- Check the console output first — the catch logs the real StorageError with its message ('Object not found' vs 'row-level security').
- Confirm assistant.image_path actually exists in the bucket via the Supabase dashboard storage browser.
- Add a storage.objects SELECT policy on assistant_images for authenticated users (or the object owner) so signed URLs can be issued.
- Re-throw or return null explicitly from the catch so callers can distinguish 'no image' from 'fetch failed'.
Example fix
// before
} catch (error) {
console.error(error)
}
// after
} catch (error) {
console.error(`Failed to sign URL for ${filePath}:`, error)
return null
} Defensive patterns
Strategy: fallback
Validate before calling
if (!filePath || filePath.length === 0) {
// nothing to sign; skip the call
} Type guard
const isSignedUrlResult = (
r: unknown
): r is { signedUrl: string } =>
typeof r === "object" && r !== null && typeof (r as any).signedUrl === "string" Try / catch
let url: string | null = null
try {
url = await getAssistantImageFromStorage(path)
} catch (e) {
console.error("signed url failed", e)
url = null // caller renders initials/placeholder
} Prevention
- Expect undefined returns from this function (its catch swallows) and null-check at call sites.
- Add a SELECT storage policy so signed URLs can be created for authenticated users.
- Don't persist signed URLs — they expire in 24h; always re-sign from the stored path.
When it happens
Trigger: Calling getAssistantImageFromStorage with a path that was deleted (e.g. after re-upload created a new timestamped path), an empty-string path, a path from another project/environment, or when no storage.objects SELECT policy covers the object for the current role.
Common situations: Rendering an avatar with a stale assistant.image_path saved in the DB; environments (local vs prod) pointing at different buckets; private bucket with no SELECT policy for authenticated users; the swallow-catch making debugging hard because only console.error fires.
Related errors
- Error deleting old image
- Error uploading image
- Error downloading file
- Error downloading message image
- Error uploading file
AI-assisted analysis of mckaywrigley/chatbot-ui@81328b61d2 (2026-08-27).
Data as JSON: /api/errors/97991fbac6c26fda.
Report an issue: GitHub.