unslothai/unsloth · error · TimeoutError
analysis {analysis_id} did not complete before the deadline
Error message
analysis {analysis_id} did not complete before the deadline What it means
TimeoutError raised inside wait_for_analysis when the monotonic clock reaches the caller-supplied deadline before the VirusTotal analysis for the given analysis id reports status "completed". It is a deadline violation on the polling loop, not an HTTP failure: every poll succeeded but the remote analysis was still queued/running.
Source
Thrown at scripts/virustotal_scan.py:542
# attempt, not a dead end: VirusTotal may well be analysing the file
# already. Raising straight out would report the asset unavailable
# after we had paid the disclosure cost of sending it, so spend the
# remaining attempt on a fresh signed URL instead.
last_error = RuntimeError("VirusTotal upload did not return an analysis id")
if attempt < attempts:
continue
raise last_error
return analysis_id
raise RuntimeError(f"VirusTotal upload failed after {attempts} attempt(s): {last_error}")
def wait_for_analysis(self, analysis_id: str, deadline: float) -> object:
"""Poll until the analysis completes or the caller's deadline passes."""
while True:
# Checked inside request() too, but raising the analysis-specific message
# here keeps the summary row readable.
if self._clock() >= deadline:
raise TimeoutError(f"analysis {analysis_id} did not complete before the deadline")
_, payload = self.request(
"GET", f"{API_ROOT}/analyses/{analysis_id}", deadline = deadline
)
attributes = _attributes(payload)
if attributes.get("status") == "completed":
return payload
if self._request_interval <= 0:
# With throttling disabled (premium key) the loop would otherwise spin.
self._sleep(1.0)
def _build_multipart(path: Path) -> tuple[bytes, str]:
"""Encode `path` as a single-part multipart/form-data body under the field `file`."""
boundary = f"----UnslothDesktopScan{uuid.uuid4().hex}"
head = (
f"--{boundary}\r\n"
f'Content-Disposition: form-data; name="file"; filename="{path.name}"\r\n'
"Content-Type: application/octet-stream\r\n\r\n"View on GitHub (pinned to 203007d190)
Solutions
- Increase the deadline passed to wait_for_analysis, sized to the uploaded file's size (large files take minutes, not seconds).
- Retain the analysis id: the upload itself succeeded, so you can poll the same id again later instead of re-uploading and paying the disclosure cost twice.
- Check the analysis status via GET /analyses/{id} manually to see whether it is queued vs failed.
- If this happens consistently for small files, check VirusTotal service status and your request interval/throttling settings.
Example fix
# before deadline = time.monotonic() + 60 payload = vt.wait_for_analysis(analysis_id, deadline) # after deadline = time.monotonic() + 15 * 60 # large uploads take minutes payload = vt.wait_for_analysis(analysis_id, deadline)
Defensive patterns
Strategy: retry
Validate before calling
deadline = max(deadline, time.monotonic() + size_based_budget(path)) # e.g. 60s per 100MB, floor 5min
Try / catch
try:
payload = vt.wait_for_analysis(analysis_id, deadline)
except TimeoutError:
# upload succeeded; persist analysis_id and poll again later instead of re-uploading
schedule_retry(analysis_id) Prevention
- Scale the polling deadline with uploaded file size.
- Persist the analysis id so a timeout never forces a second upload of sensitive assets.
- Distinguish TimeoutError from RuntimeError in handlers: one means 'wait longer', the other means 'upload failed'.
When it happens
Trigger: Polling GET {API_ROOT}/analyses/{analysis_id} until the deadline while VirusTotal still returns status 'queued' or 'running'; a very large uploaded file whose analysis exceeds the deadline; VirusTotal backend backlogs; a deadline computed too tight relative to the file size.
Common situations: Scanning multi-hundred-MB model or dataset artifacts where VirusTotal analysis routinely takes many minutes; deadline derived from a global run timeout that leaves only seconds for analysis; periods of VirusTotal slowness; request interval misconfigured so polls are too sparse to observe completion in time.
Related errors
- VirusTotal upload failed after {attempts} attempt(s): {last_
- Timeout waiting for '{expected_type}' response after {timeou
- Could not reach ChatGPT authentication.
- Timeout waiting for '{expected_type}' response (no activity
- sd-cli timed out after {timeout}s
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/c2629adeb8d828a0.
Report an issue: GitHub.