mckaywrigley/chatbot-ui · warning
Image must be less than ${imageSizeLimit / 1000000}MB
Error message
Image must be less than ${imageSizeLimit / 1000000}MB What it means
Thrown by uploadProfileImage when the image File exceeds the hardcoded 2000000-byte (2MB) limit — the strictest of this app's three image limits (profile 2MB, assistant/message 6MB). It's a client-side check before any Supabase Storage call, so it fires synchronously with no network round-trip. The literal is defined in db/storage/profile-images.ts and is not env-configurable.
Source
Thrown at db/storage/profile-images.ts:13
import { supabase } from "@/lib/supabase/browser-client"
import { Tables } from "@/supabase/types"
export const uploadProfileImage = async (
profile: Tables<"profiles">,
image: File
) => {
const bucket = "profile_images"
const imageSizeLimit = 2000000 // 2MB
if (image.size > imageSizeLimit) {
throw new Error(`Image must be less than ${imageSizeLimit / 1000000}MB`)
}
const currentPath = profile.image_path
let filePath = `${profile.user_id}/${Date.now()}`
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, {View on GitHub (pinned to 81328b61d2)
Solutions
- Resize/compress the avatar client-side before upload — profile images render small, so re-encode to ~512px JPEG/WebP at 80% quality, which lands well under 2MB.
- Pre-check image.size in the picker UI and warn the user before submission.
- If 2MB is too strict for your users, raise the constant in db/storage/profile-images.ts.
- Accept HEIC but convert to JPEG client-side, since iPhone originals frequently exceed the cap.
Example fix
// before
const result = await uploadProfileImage(profile, rawFile) // 4MB photo -> throws
// after
const compressed = await resizeImage(rawFile, { maxDim: 512, quality: 0.8 })
const result = await uploadProfileImage(profile, compressed) Defensive patterns
Strategy: validation
Validate before calling
const MAX = 2_000_000
if (image.size > MAX) {
image = await resizeImage(image, { maxDim: 512, quality: 0.8 })
}
if (image.size > MAX) {
toast.error("Profile image must be under 2MB")
return
} Type guard
const isValidProfileImage = (f: File): boolean =>
f.type.startsWith("image/") && f.size <= 2_000_000 Try / catch
try {
const { path, url } = await uploadProfileImage(profile, image)
} catch (e) {
if (e instanceof Error && e.message.includes("less than 2MB")) {
toast.error("Please choose a smaller image (under 2MB).")
} else { throw e }
} Prevention
- Auto-resize avatars client-side to ~512px before upload — small renders make 2MB generous.
- Pre-check size in the picker so users get feedback before submitting.
- Remember profile images have the strictest limit (2MB) vs assistant/message (6MB).
When it happens
Trigger: Uploading a profile photo with image.size > 2000000: typical phone camera photos (3-15MB), PNG exports, or un-compressed canvas blobs. Any File object over 2MB triggers it immediately on submission.
Common situations: Users uploading full-resolution phone portraits; avatars cropped client-side but exported as lossless PNG at high resolution; developers confused because the same photo works for assistant images (6MB) but fails here; UI not pre-validating so the throw appears as a generic error toast.
Related errors
- Image must be less than ${imageSizeLimit / 1000000}MB
- File must be less than ${Math.floor(SIZE_LIMIT / 1000000)}MB
AI-assisted analysis of mckaywrigley/chatbot-ui@81328b61d2 (2026-08-27).
Data as JSON: /api/errors/69951f140d9bce3d.
Report an issue: GitHub.