{"record":{"id":"7c2227f33556aef1","repo":"unslothai/unsloth","slug":"unsupported-file-type-ext-allowed-allowed","errorCode":null,"errorMessage":"Unsupported file type: {ext}. Allowed: {allowed}","messagePattern":"Unsupported file type: (.+?)\\. Allowed: (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"studio/backend/hub/services/datasets/local.py","lineNumber":296,"sourceCode":"    name = Path(filename).name.strip().replace(\"\\x00\", \"\")\n    if not name:\n        return \"dataset_upload\"\n    return name\n\n\ndef _upload_too_large(limit_label: str) -> HTTPException:\n    return HTTPException(\n        status_code = 413,\n        detail = f\"Training dataset upload too large. Maximum is {limit_label}.\",\n    )\n\n\ndef _upload_destination(filename: str) -> tuple[str, Path, int, str]:\n    filename = _sanitize_filename(filename)\n    ext = Path(filename).suffix.lower()\n    if ext not in LOCAL_UPLOAD_EXTS:\n        allowed = \", \".join(sorted(LOCAL_UPLOAD_EXTS))\n        raise HTTPException(\n            status_code = 400,\n            detail = f\"Unsupported file type: {ext}. Allowed: {allowed}\",\n        )\n\n    limit_mb = get_upload_limit_mb()\n    max_bytes = upload_limit_bytes(limit_mb)\n    max_label = upload_limit_label(limit_mb)\n    ensure_dir(DATASET_UPLOAD_DIR)\n    stem = Path(filename).stem\n    stored_name = f\"{uuid.uuid4().hex}_{stem}{ext}\"\n    return filename, DATASET_UPLOAD_DIR / stored_name, max_bytes, max_label\n\n\ndef _native_upload_dataset_response(native_path_lease: str) -> UploadDatasetResponse:\n    from utils.native_path_leases import NativePathLeaseError, verify_native_path_lease\n\n    try:\n        grant = verify_native_path_lease(","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/hub/services/datasets/local.py#L278-L314","documentation":"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.","triggerScenarios":"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.","commonSituations":"Users dragging Excel or zip archives into the upload dropzone; Mac users uploading files with hidden double extensions; automated pipelines pushing feather/arrow files.","solutions":["Convert to parquet or csv before uploading — fastest and best supported downstream.","Mirror the allowed-extension list in the client's file picker (accept attribute) so the attempt never reaches the server.","Ensure the filename you send retains its true suffix after sanitization (no null bytes/path separators mangled the name).","For Excel/zip sources, export to csv/parquet as a pre-upload step in your pipeline."],"exampleFix":"<!-- before -->\n<input type=\"file\" id=\"ds\">\n<!-- after -->\n<input type=\"file\" id=\"ds\" accept=\".parquet,.json,.jsonl,.csv\">","handlingStrategy":"type-guard","validationCode":"LOCAL_UPLOAD_EXTS = {\".parquet\", \".json\", \".jsonl\", \".csv\"}\n\ndef uploadable(filename: str) -> bool:\n    from pathlib import Path\n    return Path(filename).suffix.lower() in LOCAL_UPLOAD_EXTS","typeGuard":"def is_uploadable_file(file) -> TypeGuard[UploadFile]:\n    name = getattr(file, \"filename\", \"\") or \"\"\n    return Path(name).suffix.lower() in {\".parquet\", \".json\", \".jsonl\", \".csv\"}","tryCatchPattern":null,"preventionTips":["Set the file input's accept attribute to the allowed extensions (use the exact list from the error detail).","Convert Excel/zip sources to csv/parquet upstream in your data pipeline.","Sanitize filenames client-side (strip paths) so the true suffix reaches the server."],"tags":["upload","validation","file-format","http-400"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}