{"record":{"id":"5828c71d7f8a4367","repo":"MuntashirAkon/AppManager","slug":"fetch-error","errorCode":null,"errorMessage":"Fetch error: ","messagePattern":"Fetch error: ","errorType":"exception","errorClass":"FileNotFoundException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/scanner/vt/VirusTotal.java","lineNumber":117,"sourceCode":"    public VirusTotal(@NonNull String apiKey) {\n        mApiKey = Objects.requireNonNull(apiKey);\n    }\n\n    public void fetchFileReportOrScan(@NonNull Path file,\n                                      @NonNull String checksum,\n                                      @NonNull FullScanResponseInterface response)\n            throws IOException {\n        ResponseV3<VtFileReport> responseReport = fetchFileReport(checksum);\n        if (responseReport.response != null && responseReport.response.hasReport()) {\n            // A report is found\n            response.onReportReceived(responseReport.response);\n            return;\n        }\n        // No report found: either failed or still queued\n        boolean queued = responseReport.response != null && !responseReport.response.hasReport();\n        if (!queued && !responseReport.shouldRetry()) {\n            // Retry is not available\n            throw new FileNotFoundException(\"Fetch error: \" + responseReport.error);\n        }\n        // Scan or retry\n        VtError error = Objects.requireNonNull(responseReport.error);\n        boolean waitFirst = false;\n        if (\"NotFoundError\".equals(error.code)) {\n            // Initiate scan\n            if (!response.uploadFile()) {\n                // Scanning disabled\n                throw new FileNotFoundException(\"File not found in VirusTotal.\");\n            }\n            waitFirst = true;\n            PowerManager.WakeLock wakeLock = CpuUtils.getPartialWakeLock(\"vt_upload\");\n            wakeLock.acquire();\n            try {\n                long fileSize = file.length();\n                if (fileSize > 650_000_000) {\n                    throw new IOException(\"APK is larger than 650 MB.\");\n                }","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/scanner/vt/VirusTotal.java#L99-L135","documentation":"VirusTotal.fetchFileReportOrScan fetches a file report and, when no report exists and the response is neither queued nor retryable, throws FileNotFoundException(\"Fetch error: \" + responseReport.error). It signals the VT lookup definitively failed (e.g. quota/auth errors) with no retry path.","triggerScenarios":"Calling fetchFileReportOrScan when the VT API returns a non-recoverable error (invalid API key, exceeded quota, request refused) such that responseReport.shouldRetry() is false and the report is not queued.","commonSituations":"Expired or missing VirusTotal API key; daily/public-API rate quota exhausted; VT service error responses.","solutions":["Read the appended responseReport.error in the message to identify the VT error code and fix the cause (API key, quota).","Verify the VirusTotal API key in App Manager settings is valid.","Retry later if the error indicates quota exhaustion; consider a premium key for higher limits.","Catch FileNotFoundException around the call and show the error instead of crashing the scanner flow."],"exampleFix":"// before\nVtFileReport report = vt.fetchFileReportOrScan(file); // throws\n// after\ntry {\n    VtFileReport report = vt.fetchFileReportOrScan(file);\n} catch (FileNotFoundException e) {\n    Log.w(TAG, \"VT lookup failed: \" + e.getMessage());\n}","handlingStrategy":"try-catch","validationCode":"// Verify the API key before scanning:\nif (apiKey == null || apiKey.isEmpty()) {\n    throw new IllegalStateException(\"VirusTotal API key not configured.\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    VtFileReport r = vt.fetchFileReportOrScan(file);\n} catch (FileNotFoundException e) {\n    Log.w(TAG, \"VT fetch failed: \" + e.getMessage()); // message contains VT error\n}","preventionTips":["Keep a valid VirusTotal API key configured.","Watch for quota exhaustion and back off instead of retrying immediately.","Handle non-retryable VT errors distinctly from transient ones."],"tags":["network","api","virus-total"],"backgroundTag":"api-error-response","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}