unslothai/unsloth · warning · HTTPException

gguf_variant is required when export_type is 'gguf'

Error message

gguf_variant is required when export_type is 'gguf'

What it means

Thrown by DELETE /delete-finetuned when export_type is "gguf" but gguf_variant is absent/empty. GGUF exports can hold several quantization variants (Q4_K_M, Q8_0, ...) side by side in one export directory, so the endpoint deletes one variant at a time and refuses to guess. The check happens before any path validation, so nothing is modified.

Source

Thrown at studio/backend/routes/models.py:2909

    gguf_variant: Optional[str] = Body(None),
    current_subject: str = Depends(get_current_subject),
):
    """Delete an Unsloth-trained or exported model from disk.

    Only paths under Unsloth's outputs/exports roots are accepted.
    Exported GGUF entries can delete one quant variant at a time.
    """
    if source not in {"training", "exported"}:
        raise HTTPException(
            status_code = 400,
            detail = "Only trained or exported Unsloth models can be deleted",
        )

    if not model_path or not model_path.strip():
        raise HTTPException(status_code = 400, detail = "model_path is required")

    if export_type == "gguf" and not gguf_variant:
        raise HTTPException(
            status_code = 400,
            detail = "gguf_variant is required when export_type is 'gguf'",
        )

    raw_path = Path(model_path).expanduser()
    if source == "training":
        target_path = raw_path
        allowed_root = outputs_root()
    else:
        allowed_root = exports_root()
        target_path = (
            raw_path.parent
            if export_type == "gguf" and raw_path.suffix.lower() == ".gguf"
            else raw_path
        )

    allowed_root = allowed_root.resolve()
    delete_path = Path(os.path.abspath(str(target_path)))

View on GitHub (pinned to 203007d190)

Solutions

  1. Include the quant variant: {"model_path": "/exports/my-model-gguf", "source": "exported", "export_type": "gguf", "gguf_variant": "Q4_K_M"}.
  2. If you actually want the whole export directory gone, omit export_type (or set it to a non-gguf value) so the directory delete path runs.
  3. Pick the variant from the UI row / scan result rather than hardcoding, since only variants actually present on disk can be deleted (see the 404 'Variant ... not found on disk').

Example fix

# before
requests.delete('/delete-finetuned', json={'model_path': p, 'source': 'exported', 'export_type': 'gguf'})
# after
requests.delete('/delete-finetuned', json={'model_path': p, 'source': 'exported', 'export_type': 'gguf', 'gguf_variant': 'Q4_K_M'})
Defensive patterns

Strategy: validation

Validate before calling

if (payload.export_type === 'gguf' && !(payload.gguf_variant ?? '').trim()) {
  throw new Error("gguf_variant is required when export_type is 'gguf'");
}

Type guard

function isCompleteGgufDelete(payload) {
  return payload.export_type !== 'gguf' || typeof payload.gguf_variant === 'string' && payload.gguf_variant.trim().length > 0;
}

Prevention

When it happens

Trigger: Body {"model_path": "/exports/my-model-gguf", "source": "exported", "export_type": "gguf"} with no gguf_variant; or gguf_variant: "" / null. Passing export_type: "gguf" while source: "training" also hits this because the gguf branch is keyed only on export_type.

Common situations: Frontend delete dialog forwards export_type from the row but drops the variant selector when the user clicks too fast; API scripts written before per-variant GGUF deletion was introduced (older versions deleted the whole directory); confusing export_type: "gguf" with a generic type tag.

Related errors


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