unslothai/unsloth · error · RuntimeError

VirusTotal hash lookup returned a malformed body

Error message

VirusTotal hash lookup returned a malformed body

What it means

Thrown in the load-failure rollback path (use-chat-model-runtime.ts:1574-1590) when a model switch failed AFTER the previous model had been unloaded, and the previous model was loaded from a native file-picker path whose one-time, expiring nativePathToken could not be consumed (consumeNativePathToken threw). Because the previous model can only be reloaded through that signed lease, automatic rollback is impossible and the user must re-select the file manually. This error replaces/masks the original load error.

Source

Thrown at scripts/virustotal_scan.py:470

        Doing this first is both a quota saving and a disclosure saving: a bundle that
        VirusTotal already holds gains nothing from being uploaded again.
        """
        status, payload = self.request(
            "GET",
            f"{API_ROOT}/files/{sha256}",
            allow_status = (404,),
            deadline = deadline,
        )
        if status == 404:
            return None
        if not isinstance(payload, dict):
            # A 200 whose body did not parse (a proxy error page, a truncated read)
            # proves nothing about whether VirusTotal holds this file. Returning None
            # here would be indistinguishable from a 404 and would upload the bundle,
            # which is the one outcome the lookup exists to avoid: an unnecessary
            # disclosure of an unreleased build. Fail closed and let the caller
            # record the asset as unavailable instead.
            raise RuntimeError("VirusTotal hash lookup returned a malformed body")
        return payload

    def upload(
        self,
        path: Path,
        deadline: float | None = None,
    ) -> str:
        """Upload via the large-file flow and return the analysis id.

        Every desktop bundle is 41-46 MB, which is over the 32 MB cap on
        `POST /files`, so the signed upload URL is the only path that works here.

        Each signed URL is SINGLE USE, so the POST is issued with retries disabled.
        Replaying one after, say, the response body failed to read would be rejected
        no matter how many times we tried, and would report the asset as unavailable
        while an analysis was in fact already running. Retrying instead means going
        back for a fresh URL, which is what the loop below does.
        """

View on GitHub (pinned to 203007d190)

Solutions

  1. Re-select the previous local model file in the file picker and load it again — this mints a fresh native-path token.
  2. Check the server logs for why the target model failed to load (that root cause started the rollback) and fix it before retrying the switch.
  3. To avoid repeat occurrences, prefer catalog/indexed models over raw file picks for models you switch away from and back to.
  4. Freeze/stop other GPU consumers first if the target failed with out-of-memory so the retry succeeds.
Defensive patterns

Strategy: fallback

Validate before calling

function isNativeFilePick(nativePathToken: string | undefined): boolean {
  return typeof nativePathToken === 'string' && nativePathToken.length > 0;
}

Type guard

function isRollbackTokenError(e: unknown): e is Error {
  return e instanceof Error && /please re-select the file/.test(e.message);
}

Try / catch

try {
  await loadModel(selection);
} catch (error) {
  if (isRollbackTokenError(error)) {
    // manual fallback: prompt the user to re-pick the previous local file and load it
    promptReSelectPreviousFile();
  } else throw error;
}

Prevention

When it happens

Trigger: Load model B while model A (chosen via the native file picker) is resident; A gets unloaded; B's load fails; then consumeNativePathToken(A's token) throws because the token was already consumed by this attempt's earlier lease exchange or expired. The catch converts that into this 'please re-select the file' error.

Common situations: Switching from a locally-picked GGUF/safetensors file to another model that then fails to load (OOM, bad repo id); tokens expiring during long loads; a failed switch retried after the single-use token was spent.

Understand the failure class

Related errors


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