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
- Re-select the previous local model file in the file picker and load it again — this mints a fresh native-path token.
- 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.
- To avoid repeat occurrences, prefer catalog/indexed models over raw file picks for models you switch away from and back to.
- 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
- Keep the file-picker path handy (recent files list) so recovery is one click.
- Fix the root cause of the failed target load (VRAM, repo id) before switching away from a native-pick model.
- Prefer indexed/catalog models when you expect to switch models frequently — their rollback needs no token.
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
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- deadline reached while pacing before {method} {_redact_url(u
- VirusTotal returned HTTP {status} for {_redact_url(url)}
- VirusTotal request failed after {max_attempts} attempt(s): {
- family {getattr(fam, 'name', fam)!r} declares no prequant_fi
- lockfile not found: {path}
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/de7e852d9c07cc06.
Report an issue: GitHub.