unslothai/unsloth · error · FileNotFoundError

no .safetensors/.gguf LoRA file found in '{repo_id}'

Error message

no .safetensors/.gguf LoRA file found in '{repo_id}'

What it means

Raised by the LoRA resolver when scanning a Hugging Face repo's file listing yields no top-level .safetensors or .gguf file suitable as a LoRA adapter. The resolver only considers files at the repo root (paths without '/'), so adapters nested in subfolders never qualify. It is a FileNotFoundError so callers can map it to a 4xx via the Hub-error handler in resolve_specs.

Source

Thrown at studio/backend/core/inference/diffusion_lora.py:284

def _pick_repo_weight_file(repo_id: str, hf_token: Optional[str]) -> str:
    """Pick the single LoRA weight file in an HF repo (prefer safetensors)."""
    from huggingface_hub import HfApi

    files = HfApi(token = hf_token).list_repo_files(repo_id)
    safes = [f for f in files if f.lower().endswith(".safetensors") and "/" not in f]
    if len(safes) == 1:
        return safes[0]
    # Prefer a lora-hinting filename, else the first safetensors, else a gguf.
    for f in safes:
        if "lora" in f.lower():
            return f
    if safes:
        return safes[0]
    ggufs = [f for f in files if f.lower().endswith(".gguf") and "/" not in f]
    if ggufs:
        return ggufs[0]
    raise FileNotFoundError(f"no .safetensors/.gguf LoRA file found in '{repo_id}'")


def _scrub_hub_url(msg: str) -> str:
    """Strip embedded http(s) URLs from a Hub error message before it hits a 400 body."""
    cleaned = re.sub(r"https?://\S+", "", msg)
    # Collapse the whitespace the URL removal leaves behind.
    return re.sub(r"\s{2,}", " ", cleaned).strip()


def resolve_specs(
    specs: list[tuple[str, float]],
    *,
    family: Optional[str] = None,
    hf_token: Optional[str] = None,
    cancel_event: Optional[threading.Event] = None,
) -> list[ResolvedLora]:
    """Resolve request (id, weight) pairs, dropping zero-weight entries.

View on GitHub (pinned to 203007d190)

Solutions

  1. Verify the repo actually contains a top-level .safetensors or .gguf file (huggingface-cli ls or the HF web UI)
  2. If the adapter is nested in a subfolder, download it locally and point the spec at the local file path instead of the repo id
  3. Convert .bin/.pt LoRA weights to .safetensors (safetensors convert or automatic1111 conversion scripts)
  4. Check the repo id for typos and confirm it is a LoRA adapter repo, not a base model

Example fix

// before
specs = [("user/nested-lora", 0.8)]  // adapter lives in nested-lora/adapter_model.safetensors
// after
specs = [("user/nested-lora/resolve/main/adapter_model.safetensors", 0.8)]
// or download locally and pass the local path
Defensive patterns

Strategy: validation

Validate before calling

from huggingface_hub import list_repo_files

def has_root_lora(repo_id: str) -> bool:
    files = list_repo_files(repo_id)
    root = [f for f in files if "/" not in f]
    return any(f.lower().endswith((".safetensors", ".gguf")) for f in root)

Try / catch

try:
    resolve_specs([...])
except FileNotFoundError as e:
    # map to 400 with the (already hub-url-scrubbed) message
    return JSONResponse(status_code=400, content={"detail": str(e)})

Prevention

When it happens

Trigger: Calling resolve/download of a LoRA spec whose repo_id contains only subfolder weights (e.g. 'some-org/lora-pack/subdir/adapter.safetensors' layout), only non-weight files (README, .bin, .pt), or is empty. Also triggered by mistyping a repo id that resolves to a non-adapter repo.

Common situations: User pastes a diffusers-format LoRA repo where the adapter lives under a subfolder; repo uses .bin or .pt format only; repo id points at a base model rather than a LoRA; HF returned an empty file list due to a truncated listing.

Related errors


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