jamiepine/voicebox · warning · ValueError
Invalid format '{img_format}'. Allowed formats: PNG, JPEG, W
Error message
Invalid format '{img_format}'. Allowed formats: PNG, JPEG, WEBP What it means
Returned by validate_image() when PIL successfully loads the image but its normalized format is not in {PNG, JPEG, WEBP}. MPO and JPG are normalized to JPEG before the check. upload_avatar() re-raises this message as a ValueError. The allow-list keeps avatar storage predictable and avoids rarely-supported formats.
Source
Thrown at backend/services/profiles.py:649
) -> VoiceProfileResponse:
"""
Upload and process avatar image for a profile.
Args:
profile_id: Profile ID
image_path: Path to uploaded image file
db: Database session
Returns:
Updated profile
"""
profile = db.query(DBVoiceProfile).filter_by(id=profile_id).first()
if not profile:
raise ValueError(f"Profile {profile_id} not found")
is_valid, error_msg = validate_image(image_path)
if not is_valid:
raise ValueError(error_msg)
if profile.avatar_path:
old_avatar = config.resolve_storage_path(profile.avatar_path)
if old_avatar is not None and old_avatar.exists():
old_avatar.unlink()
# Determine file extension from uploaded file
from PIL import Image
with Image.open(image_path) as img:
# Normalize JPEG variants (MPO is multi-picture format from some cameras)
img_format = img.format
if img_format in ("MPO", "JPG"):
img_format = "JPEG"
ext_map = {"PNG": ".png", "JPEG": ".jpg", "WEBP": ".webp"}
ext = ext_map.get(img_format, ".png")
View on GitHub (pinned to 51f49dea19)
Solutions
- Convert the image to PNG, JPEG, or WEBP before uploading.
- On the client, restrict the file picker accept attribute to image/png,image/jpeg,image/webp.
- If you genuinely need another format, add it to ALLOWED_FORMATS and the post-normalization set in backend/utils/images.py (and confirm process_avatar handles it).
- For HEIC, install pillow-heif and normalize to JPEG.
Example fix
// before: uploading avatar.gif
// after: convert to PNG
from PIL import Image
Image.open('avatar.gif').convert('RGB').save('avatar.png', 'PNG') Defensive patterns
Strategy: validation
Validate before calling
from PIL import Image
def is_allowed_image_format(path: str) -> bool:
with Image.open(path) as img:
fmt = img.format
if fmt in ('MPO', 'JPG'):
fmt = 'JPEG'
return fmt in {'PNG', 'JPEG', 'WEBP'} Try / catch
try:
profile = await upload_avatar(profile_id, image_path, db)
except ValueError as e:
if 'Invalid format' in str(e):
raise HTTPException(415, str(e))
raise Prevention
- Restrict the file picker to image/png,image/jpeg,image/webp on the client.
- Convert unsupported formats before upload.
- Keep ALLOWED_FORMATS and the post-normalization set in sync if you extend formats.
When it happens
Trigger: Uploading a GIF, BMP, TIFF, WEBP-variant, or HEIC file as an avatar; a file with a misleading extension whose actual PIL-detected format is unsupported.
Common situations: Users exporting from design tools to GIF/BMP; screenshots saved as TIFF; HEIC photos from iPhones that PIL reads as HEIF (requires plugins); animated stickers in GIF form.
Related errors
- File size exceeds maximum of 5MB
- Invalid image file: {str(e)}
- Unsupported audio format '{suffix}'. Allowed: {sorted(IMPORT
- Profile not found: {profile_id}
- No samples found for profile {profile_id}
AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12).
Data as JSON: /api/errors/eddf01a035e351e1.
Report an issue: GitHub.