unslothai/unsloth · error · HTTPException

Unsupported file type: {ext}. Allowed: {allowed}

Error message

Unsupported file type: {ext}. Allowed: {allowed}

What it means

HTTP 400 from `_upload_destination` when the sanitized upload filename's extension is not in LOCAL_UPLOAD_EXTS. It fires before any bytes are written or size checks run, and the detail enumerates the allowed set so clients can validate upfront. Filename is sanitized first (path stripped, null bytes removed), so only the final suffix matters.

Source

Thrown at studio/backend/hub/services/datasets/local.py:296

    name = Path(filename).name.strip().replace("\x00", "")
    if not name:
        return "dataset_upload"
    return name


def _upload_too_large(limit_label: str) -> HTTPException:
    return HTTPException(
        status_code = 413,
        detail = f"Training dataset upload too large. Maximum is {limit_label}.",
    )


def _upload_destination(filename: str) -> tuple[str, Path, int, str]:
    filename = _sanitize_filename(filename)
    ext = Path(filename).suffix.lower()
    if ext not in LOCAL_UPLOAD_EXTS:
        allowed = ", ".join(sorted(LOCAL_UPLOAD_EXTS))
        raise HTTPException(
            status_code = 400,
            detail = f"Unsupported file type: {ext}. Allowed: {allowed}",
        )

    limit_mb = get_upload_limit_mb()
    max_bytes = upload_limit_bytes(limit_mb)
    max_label = upload_limit_label(limit_mb)
    ensure_dir(DATASET_UPLOAD_DIR)
    stem = Path(filename).stem
    stored_name = f"{uuid.uuid4().hex}_{stem}{ext}"
    return filename, DATASET_UPLOAD_DIR / stored_name, max_bytes, max_label


def _native_upload_dataset_response(native_path_lease: str) -> UploadDatasetResponse:
    from utils.native_path_leases import NativePathLeaseError, verify_native_path_lease

    try:
        grant = verify_native_path_lease(

View on GitHub (pinned to 203007d190)

Solutions

  1. Convert to parquet or csv before uploading — fastest and best supported downstream.
  2. Mirror the allowed-extension list in the client's file picker (accept attribute) so the attempt never reaches the server.
  3. Ensure the filename you send retains its true suffix after sanitization (no null bytes/path separators mangled the name).
  4. For Excel/zip sources, export to csv/parquet as a pre-upload step in your pipeline.

Example fix

<!-- before -->
<input type="file" id="ds">
<!-- after -->
<input type="file" id="ds" accept=".parquet,.json,.jsonl,.csv">
Defensive patterns

Strategy: type-guard

Validate before calling

LOCAL_UPLOAD_EXTS = {".parquet", ".json", ".jsonl", ".csv"}

def uploadable(filename: str) -> bool:
    from pathlib import Path
    return Path(filename).suffix.lower() in LOCAL_UPLOAD_EXTS

Type guard

def is_uploadable_file(file) -> TypeGuard[UploadFile]:
    name = getattr(file, "filename", "") or ""
    return Path(name).suffix.lower() in {".parquet", ".json", ".jsonl", ".csv"}

Prevention

When it happens

Trigger: Uploading .xlsx, .zip, .tsv, .txt or extension-less files through the dataset upload endpoint; a client sending the full path or a filename whose real suffix differs from the displayed one.

Common situations: Users dragging Excel or zip archives into the upload dropzone; Mac users uploading files with hidden double extensions; automated pipelines pushing feather/arrow files.

Related errors


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/7c2227f33556aef1. Report an issue: GitHub.