affaan-m/ECC · warning · ValidationError
Unsupported file type.
Error message
Unsupported file type.
What it means
validate_file_type() in the django-security skill reads the first 2048 bytes, gets the MIME via python-magic, and raises django ValidationError('Unsupported file type.') if the detected MIME is not in ALLOWED_MIMES (image/jpeg, image/png, image/gif, application/pdf). This is a magic-byte allowlist: the browser-supplied extension and Content-Type are irrelevant at this stage — only the detected content type matters. libmagic must be installed (libmagic / file) or the call itself will fail before this line.
Source
Thrown at skills/django-security/SKILL.md:415
ALLOWED_MIMES = {
'image/jpeg', 'image/png', 'image/gif', 'application/pdf',
}
MIME_TO_EXTENSIONS = {
'image/jpeg': {'.jpg', '.jpeg'},
'image/png': {'.png'},
'image/gif': {'.gif'},
'application/pdf': {'.pdf'},
}
def validate_file_type(value):
"""Validate file type using magic bytes and cross-check extension."""
mime = magic.from_buffer(value.read(2048), mime=True)
value.seek(0)
if mime not in ALLOWED_MIMES:
raise ValidationError('Unsupported file type.')
ext = os.path.splitext(value.name)[1].lower()
if ext not in MIME_TO_EXTENSIONS.get(mime, set()):
raise ValidationError('File extension does not match file content.')
def validate_file_size(value):
"""Validate file size (max 5MB)."""
if value.size > 5 * 1024 * 1024:
raise ValidationError('File too large. Max size is 5MB.')
# models.py
class Document(models.Model):
file = models.FileField(
upload_to='documents/',
validators=[validate_file_type, validate_file_size]
)
```View on GitHub (pinned to 01e15490f0)
Solutions
- Confirm the upload is one of jpeg/png/gif/pdf; convert webp/heic before upload.
- Extend ALLOWED_MIMES (and add the matching extensions to MIME_TO_EXTENSIONS) if a new type is genuinely supported.
- Verify libmagic is installed and its database is current.
- Do not trust the browser Content-Type — this validator intentionally ignores it.
Example fix
// before
ALLOWED_MIMES = {'image/jpeg', 'image/png', 'image/gif', 'application/pdf'}
// after — add webp support
ALLOWED_MIMES = {'image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'image/webp'}
MIME_TO_EXTENSIONS = {
'image/jpeg': {'.jpg', '.jpeg'},
'image/png': {'.png'},
'image/gif': {'.gif'},
'application/pdf': {'.pdf'},
'image/webp': {'.webp'},
} Defensive patterns
Strategy: validation
Validate before calling
import magic
ALLOWED_MIMES = {'image/jpeg', 'image/png', 'image/gif', 'application/pdf'}
def will_pass_mime(path: str) -> bool:
with open(path, "rb") as f:
mime = magic.from_buffer(f.read(2048), mime=True)
return mime in ALLOWED_MIMES Type guard
from django.core.exceptions import ValidationError
def is_unsupported_file(exc: BaseException) -> bool:
return isinstance(exc, ValidationError) and "Unsupported file type" in str(exc) Try / catch
from django.core.exceptions import ValidationError
try:
validate_file_type(uploaded)
except ValidationError as e:
if "Unsupported file type" in str(e):
return JsonResponse({"error": "Only JPEG, PNG, GIF, PDF allowed"}, status=400)
raise Prevention
- Pre-validate MIME client-side and convert webp/heic to png.
- Keep libmagic installed and its database updated.
- Document the allowed MIME set to users in the upload UI.
- Extend ALLOWED_MIMES and MIME_TO_EXTENSIONS together when adding a type.
When it happens
Trigger: Uploading a file whose magic-byte MIME is outside the allowed set — e.g. webp, heic, svg, docx, txt, video; or a file libmagic misidentifies due to a stale magic database.
Common situations: Users uploading webp/heic screenshots (not in the allowlist); SVG logos; Office documents where only PDF is accepted; libmagic returning a non-standard MIME; libmagic not installed so from_buffer errors.
Related errors
- File extension does not match file content.
- File too large. Max size is 5MB.
- Invalid ECC repo root: missing install script at ${installAp
- TypeScript compiler not found. Install root dev dependencies
- Missing value for --target
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/96bebc42d3d8863f.
Report an issue: GitHub.