MuntashirAkon/AppManager · error · IOException
Scan error:
Error message
Scan error:
What it means
VirusTotal file-report/scan request completed but the API returned an error payload instead of a scan report. fetchFileReportOrScan unwraps ResponseV3 and, when there is no response object but an error string, throws IOException("Scan error: " + error) to surface the remote failure to the caller.
Solutions
- Inspect responseReport.error in the message to identify the remote cause (rate limit vs auth vs not-found).
- Verify the VirusTotal API key is valid and has remaining quota.
- Respect the waitDuration (30s) and retry with backoff when the error indicates rate limiting or pending analysis.
- Catch the IOException at the call site and surface a user-visible failure instead of crashing.
Example fix
// before
throw new IOException("Scan error: " + responseReport.error);
// after
if (responseReport.error != null && responseReport.error.contains("rate limit")) {
throw new IOException("VirusTotal rate limit exceeded, try again later");
}
throw new IOException("Scan error: " + responseReport.error); Defensive patterns
Strategy: try-catch
Validate before calling
if (apiKey == null || apiKey.isEmpty()) throw new IllegalStateException("VT API key missing");
if (responseReport.error != null && !responseReport.error.isEmpty()) {
// error already known before unwrapping: handle manually
} Try / catch
try {
virusTotal.fetchFileReportOrScan(file, waitDuration, response);
} catch (IOException e) {
if (e.getMessage() != null && e.getMessage().contains("rate limit")) {
// back off and retry later
} else {
// show scan-unavailable state to user
}
} Prevention
- Validate the VT API key before enqueueing scans.
- Respect the 30s waitDuration and free-tier rate limits (~4 req/min).
- Always handle IOException from fetchFileReportOrScan; VT is a remote service that can fail.
- Inspect responseReport.error strings to distinguish quota/auth/parse failures.
When it happens
Trigger: Calling fetchFileReportOrScan when the VirusTotal v3 API responds with an error: rate limit exceeded, invalid/expired API key, file not yet analyzed and no scan queued, or a network/HTTP failure captured into responseReport.error.
Common situations: Free-tier API quota exhausted (HTTP 429), wrong VT API key, polling too early before the waitDuration elapses, transient VirusTotal outages.
Related errors
- Fetch error:
- File not found in VirusTotal.
- ADB command did not produce
- ADB daemon not running.
- APK files backup is requested but no APK files have been…
AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12).
Data as JSON: /api/errors/a55e5195943b4b1b.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/main/java/io/github/muntashirakon/AppManager/scanner/vt/VirusTotal.java:170
int waitDuration = 60_000;
while (queued || responseReport.shouldRetry()) {
if (waitFirst) {
// Effectively makes it a do-while loop
waitFirst = false;
} else {
responseReport = fetchFileReport(checksum);
queued = responseReport.response != null && !responseReport.response.hasReport();
}
// Wait for result: First wait for 1 minute, then for 30 seconds
// We won't do it less than 30 seconds since the API has a limit of 4 request/minute
SystemClock.sleep(waitDuration);
// TODO: 23/5/22 Wait duration should be according to the fileSize
waitDuration = 30_000;
}
if (responseReport.response != null) {
response.onReportReceived(responseReport.response);
} else {
throw new IOException("Scan error: " + responseReport.error);
}
}
@WorkerThread
@NonNull
public ResponseV3<String> uploadFile(@NonNull String filename, @NonNull InputStream is)
throws IOException {
return uploadFile(filename, is, null);
}
@WorkerThread
@NonNull
public ResponseV3<String> uploadFile(@NonNull String filename, @NonNull InputStream is,
@Nullable String password) throws IOException {
URL url = new URL(URL_FILE_UPLOAD);
return uploadAnyFile(url, filename, is, password);
}
View on GitHub (pinned to 0152f468fc)