From 6b22c93554eb69baa967f0dabec66df2e365ab5a Mon Sep 17 00:00:00 2001 From: Sucukdeluxe Date: Sun, 8 Mar 2026 01:03:37 +0100 Subject: [PATCH] Fix auto-recovery re-download for encrypted RAR5 archives - Always force re-download once when both JVM and legacy extractors fail (suggestRedownload=true), regardless of valid archive signature - Add autoRecoveredForRedownload Set for loop protection (one attempt per archive) - Clear loop protection on package reset (clearHybridArchiveState) - Previous sibling-items check failed when other episodes were already cleaned up after hybrid extraction - Lower mini-download retry threshold from 100KB to 5KB Co-Authored-By: Claude Opus 4.6 --- src/main/download-manager.ts | 38 ++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/src/main/download-manager.ts b/src/main/download-manager.ts index 63dfb8d..60ac75e 100644 --- a/src/main/download-manager.ts +++ b/src/main/download-manager.ts @@ -95,7 +95,7 @@ const DEFAULT_LOW_THROUGHPUT_TIMEOUT_MS = 120000; const DEFAULT_LOW_THROUGHPUT_MIN_BYTES = 64 * 1024; -const MINI_DOWNLOAD_RETRY_THRESHOLD_BYTES = 100 * 1024; +const MINI_DOWNLOAD_RETRY_THRESHOLD_BYTES = 5 * 1024; const ALLDEBRID_HOST_INFO_TTL_MS = 60000; @@ -1106,6 +1106,9 @@ export class DownloadManager extends EventEmitter { // archives are not retried on every subsequent post-processing wake-up. private hybridFailedArchives = new Map>(); + /** Archives already auto-recovered via forced re-download (loop protection). */ + private autoRecoveredForRedownload = new Set(); + private reservedTargetPaths = new Map(); private claimedTargetPathByItem = new Map(); @@ -4169,6 +4172,10 @@ export class DownloadManager extends EventEmitter { if (!archiveKey) { this.hybridExtractedPaths.delete(packageId); this.hybridFailedArchives.delete(packageId); + // Also clear re-download loop protection for this package + for (const key of this.autoRecoveredForRedownload) { + if (key.startsWith(`${packageId}::`)) this.autoRecoveredForRedownload.delete(key); + } return; } @@ -4273,24 +4280,25 @@ export class DownloadManager extends EventEmitter { } if (hasValidSignature) { - // Check if other archives in this package were successfully extracted. - // If a known password worked for siblings but NOT for this archive, - // the file is very likely corrupt despite having a valid header. - const otherItemsExtracted = items.some((item) => - item.status === "completed" && isExtractedLabel(item.fullStatus) - && !archiveItems.includes(item) - ); - if (otherItemsExtracted) { + // Valid signature + suggestRedownload means both JVM and legacy extractors failed + // (CRC/password error). Even with a valid header the content can be corrupt – + // encrypted RAR5 produces "Checksum error" indistinguishable from wrong password. + // Force re-download ONCE; use autoRecoveredForRedownload Set for loop protection. + const redownloadKey = `${pkg.id}::${failure.archiveName}`; + if (this.autoRecoveredForRedownload.has(redownloadKey)) { logger.warn( - `Auto-Recovery (${scope}): ${failure.archiveName} - Signatur gueltig aber ` + - `andere Archive im Paket bereits entpackt (bekanntes Passwort existiert). ` + - `Erzwinge Re-Download aller ${archiveItems.length} Parts (wahrscheinliche Korruption)` + `Auto-Recovery (${scope}): ${failure.archiveName} uebersprungen - ` + + `wurde bereits einmal per Re-Download versucht (Loop-Schutz)` ); - corruptArchiveItems.push(...inspectedArchiveItems); - } else { - logger.warn(`Auto-Recovery (${scope}): ${failure.archiveName} uebersprungen - Dateien korrekte Groesse, Archiv-Signatur gueltig (vermutlich falsches Passwort)`); return 0; } + this.autoRecoveredForRedownload.add(redownloadKey); + logger.warn( + `Auto-Recovery (${scope}): ${failure.archiveName} - Signatur gueltig, ` + + `beide Extraktoren fehlgeschlagen (suggestRedownload). ` + + `Erzwinge Re-Download aller ${archiveItems.length} Parts` + ); + corruptArchiveItems.push(...inspectedArchiveItems); } logger.warn(