unslothai/unsloth · error · ValueError

{_cn_fs.reason}

Error message

{_cn_fs.reason}

What it means

Raised when the Hub malware preflight (`evaluate_file_security` from utils.security) blocks the requested remote ControlNet repository. Because `resolve_controlnet` accepts a bare owner/name without the trust gate, `from_pretrained` on a malicious repo would execute a pickle; the same security scan used for model loads runs here. The ValueError carries the scanner's reason string, and the check applies only to remote (non-local) ControlNet paths.

Source

Thrown at studio/backend/core/inference/diffusion.py:4838

        fam = state.family
        pipe_cls_name = getattr(fam, "controlnet_pipeline_class", None)
        model_cls_name = getattr(fam, "controlnet_model_class", None)
        if not pipe_cls_name or not model_cls_name:
            raise ValueError(f"ControlNet is not supported for the '{fam.name}' model family.")
        import diffusers

        cn_model = self._cn_models.get(resolved_cn.id)
        if cn_model is None:
            if cancel.is_set():
                raise RuntimeError(DIFFUSION_CANCELLED_MSG)
            # resolve_controlnet accepts a bare owner/name without the trust gate and from_pretrained would execute a malicious
            # pickle, so run the same Hub malware preflight. It fails OPEN, so a remote repo also forces safetensors below.
            remote_cn = not getattr(resolved_cn, "is_local", False)
            if remote_cn:
                from utils.security import evaluate_file_security
                _cn_fs = evaluate_file_security(resolved_cn.path, hf_token = state.hf_token or None)
                if _cn_fs.blocked:
                    raise ValueError(_cn_fs.reason)
            # Keep at most one ControlNet resident, else swapping ControlNets accumulates until OOM.
            if self._cn_models or self._cn_pipes:
                self._cn_models.clear()
                self._cn_pipes.clear()
                clear_gpu_cache()
            import torch

            # state.dtype is the display string ("bfloat16"), so pass the real dtype and avoid a float32 load.
            cn_dtype = getattr(torch, str(state.dtype).replace("torch.", ""), None)
            # Force safetensors for an untrusted remote repo: if the Hub scan failed open, an embedded pickle would still deserialize.
            cn_from_pretrained_kwargs: dict[str, Any] = {"cache_dir": hub_cache_dir()}
            if remote_cn:
                cn_from_pretrained_kwargs["use_safetensors"] = True
            cn_model = getattr(diffusers, model_cls_name).from_pretrained(
                resolved_cn.path,
                torch_dtype = cn_dtype,
                token = state.hf_token or None,  # blank -> anonymous
                **cn_from_pretrained_kwargs,

View on GitHub (pinned to 203007d190)

Solutions

  1. Read the reason string: it states why the repo was blocked (e.g. suspicious pickle, unsafe serialization format).
  2. Use a trusted/local ControlNet model file instead of the flagged remote repo.
  3. Pick a known-safe safetensors ControlNet repo from the Hub.
  4. Do not bypass the gate; report genuinely false positives to the scanner maintainers.
Defensive patterns

Strategy: validation

Validate before calling

# Trust only known ControlNet sources; check before generate
if not is_trusted_cn_repo(cn_id):  # your allowlist / local-path policy
    raise ValueError(f"ControlNet repo '{cn_id}' is not trusted")

Type guard

def is_safe_cn_source(cn) -> bool:
    """Local file, or remote repo pinned to safetensors-only artifacts."""
    return bool(getattr(cn, "is_local", False)) or getattr(cn, "safetensors_only", False)

Try / catch

try:
    diffusion.generate(prompt=p, controlnet=cn)
except ValueError as e:
    if "blocked" in str(e).lower() or security_scanner_reason(e):
        log_security_event(str(e)); choose_trusted_cn()
    else:
        raise

Prevention

When it happens

Trigger: Requesting a generate() with a ControlNet id that resolves to a remote Hub repo which the security scan flags (`_cn_fs.blocked` is True), with `is_local` falsy so the remote branch runs. The reason text comes directly from the security evaluation result.

Common situations: Users pasting arbitrary owner/name ControlNet repos from the Hub; typosquatted or pickle-carrying repos caught by the scanner; organizational policies where the malware preflight denies unknown repos.

Related errors


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