unslothai/unsloth · warning · HTTPException
Unsupported file type '{ext}'. Allowed: {sorted(config.UPLOA
Error message
Unsupported file type '{ext}'. Allowed: {sorted(config.UPLOAD_EXTS)} What it means
_persist_upload_stream() rejects any uploaded document whose lowercase file extension is not in config.UPLOAD_EXTS, raising HTTP 400 with the offending extension and the sorted allowlist. The extension check happens before a temp file is written, so unsupported files never touch disk.
Source
Thrown at studio/backend/routes/rag.py:117
def _sanitize_filename(name: str) -> str:
base = os.path.basename(name or "").strip() or "document"
base = _SAFE.sub("_", base)
if len(base) <= 200:
return base
# Trim the stem, not the extension: _save_upload gates on the extension, so
# a plain truncation would reject a long-named .txt as "unsupported".
stem, ext = os.path.splitext(base)
if not ext or len(ext) > 32:
return base[:200]
return stem[: 200 - len(ext)] + ext
def _persist_upload_stream(source, filename: str, *, empty_detail: str) -> tuple[str, str]:
"""Copy a validated document stream into the managed uploads root."""
ext = os.path.splitext(filename)[1].lower()
if ext not in config.UPLOAD_EXTS:
raise HTTPException(
status_code = 400,
detail = f"Unsupported file type '{ext}'. Allowed: {sorted(config.UPLOAD_EXTS)}",
)
uploads = ensure_dir(rag_uploads_root())
stored_path = str(uploads / f"{uuid.uuid4().hex}{ext}")
size = 0
cap = config.MAX_UPLOAD_BYTES
try:
with open(stored_path, "wb") as out:
while True:
block = source.read(1 << 20)
if not block:
break
size += len(block)
if cap and size > cap:
break
out.write(block)
except OSError:View on GitHub (pinned to 203007d190)
Solutions
- Match the detail string's allowlist: convert the file to an allowed format (e.g. export PDF, save as .txt/.md) and re-upload.
- If the format is genuinely needed, add its extension to config.UPLOAD_EXTS and ensure the ingestion pipeline can parse it.
- Filter the file picker / drag-drop target client-side to allowed extensions before the request.
Example fix
# before
upload('report.docx') # 400 Unsupported file type '.docx'
# after
upload('report.pdf') # extension present in config.UPLOAD_EXTS Defensive patterns
Strategy: validation
Validate before calling
import os
ALLOWED = {'.txt', '.md', '.pdf'} # mirror config.UPLOAD_EXTS
ext = os.path.splitext(filename)[1].lower()
if ext not in ALLOWED:
raise ValueError(f'convert {filename} to one of {sorted(ALLOWED)} first') Type guard
const hasAllowedExt = (name: string): boolean =>
ALLOWED_EXTS.includes(name.slice(name.lastIndexOf('.')).toLowerCase()); Try / catch
if (!hasAllowedExt(file.name)) { notify(`Only ${ALLOWED_EXTS.join(', ')} supported`); return; } Prevention
- Set the file input's accept attribute to the allowed extensions.
- Re-check the allowlist after backend upgrades — it is config-driven and can change.
- Offer in-app conversion (export to PDF/text) instead of letting users hit the 400.
When it happens
Trigger: Uploading a document with an extension outside config.UPLOAD_EXTS — e.g. .exe, .zip, .docx when only text/pdf/markdown etc. are allowed — via the browser file upload or a native-path drop.
Common situations: User drags a Word/Excel/archive file into the knowledge base; OCR-oriented workflow where the user expects .docx support but the allowlist covers only directly-ingestible text formats; case differences are fine (extension is lowercased) but different formats are not.
Related errors
- Uploaded file is empty.
- No file was provided.
- File exceeds the {cap // (1024 * 1024)} MB upload limit.
- Native path grant is required.
- Dropped file could not be read.
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/5bf89e4460146833.
Report an issue: GitHub.