unslothai/unsloth · warning · HTTPException

GGUF variant deletion requires an export directory

Error message

GGUF variant deletion requires an export directory

What it means

400 raised on the GGUF per-variant delete branch (models.py:3118): export_type="gguf" and gguf_variant are set, all load guards passed, but target_path is not a directory. _delete_gguf_variant_files rglobs an export directory for the variant's files, so it requires the export dir (e.g. exports/my-model-gguf), not a single .gguf file path — note that earlier, when the path ends in .gguf, the code moved the target to raw_path.parent for the containment checks, but this branch validates the directory explicitly.

Source

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

                for lid in getattr(backend, "loading_repo_ids", tuple)()
            ):
                raise HTTPException(
                    status_code = 409,
                    detail = "Cannot delete a model while it is loading",
                )
        except HTTPException:
            raise
        except Exception as e:
            logger.warning("Could not check the %s model before delete: %s", label, e)
            raise HTTPException(
                status_code = 503,
                detail = "Could not verify model load status before deleting",
            ) from e

    try:
        if export_type == "gguf" and gguf_variant:
            if not target_path.is_dir():
                raise HTTPException(
                    status_code = 400,
                    detail = "GGUF variant deletion requires an export directory",
                )
            deleted_count, deleted_bytes = _delete_gguf_variant_files(
                target_path,
                gguf_variant,
            )
            if deleted_count == 0:
                raise HTTPException(
                    status_code = 404,
                    detail = f"Variant {gguf_variant} not found on disk",
                )
            try:
                if not any(target_path.iterdir()):
                    target_path.rmdir()
                    _prune_empty_parents(target_path, allowed_root)
            except OSError:
                pass

View on GitHub (pinned to 203007d190)

Solutions

  1. Pass the export directory as model_path: exports/my-model-gguf (not the individual .gguf file).
  2. Drop export_type/gguf_variant entirely if you intend a plain directory or single-file delete.
  3. Verify with Path(model_path).is_dir() before sending when export_type is gguf.
  4. If a single GGUF file really must go and it is not a managed export dir, delete export_type from the payload so the non-variant branch handles it.

Example fix

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

Strategy: validation

Validate before calling

if payload.get('export_type') == 'gguf' and payload.get('gguf_variant'):
    p = Path(payload['model_path']).expanduser()
    if p.suffix.lower() == '.gguf':
        payload = {**payload, 'model_path': str(p.parent)}  # send the export dir
    if not Path(payload['model_path']).is_dir():
        raise ValueError('GGUF variant deletion needs the export directory, not a file')

Type guard

def is_gguf_variant_delete_ready(payload: dict) -> bool:
    if payload.get('export_type') != 'gguf' or not payload.get('gguf_variant'): return True  # not this branch
    p = Path(payload['model_path']).expanduser()
    return p.is_dir()

Prevention

When it happens

Trigger: Passing the .gguf file itself as model_path ({'model_path': '.../model-Q4_K_M.gguf', 'export_type': 'gguf', 'gguf_variant': 'Q4_K_M'}) when path handling did not rewrite it (e.g. different suffix casing or a non-.gguf filename); passing a model path that is a checkpoint directory from source="training" while still setting export_type="gguf"; the export dir having been replaced by a file/symlink after the UI scan.

Common situations: Confusing 'delete this one .gguf file' semantics with the endpoint's 'delete one quant variant from an export directory' semantics; reusing a training-source path with GGUF parameters; stale UI rows after manual filesystem edits.

Related errors


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